home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 37 / IOPROG_37.ISO / SOFT / Multilizer.exe / disk1 / data1.cab / data1 / [Group19]VCL Source Professional / IvDictio.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-08-10  |  138.5 KB  |  5,226 lines

  1. { Copyrights 1995-1999 Innoview Data Technologies Ltd. }
  2.  
  3. unit IvDictio;
  4.  
  5. {$I IVMULTI.INC}
  6.  
  7. interface
  8.  
  9. uses
  10. {$IFDEF WIN32}
  11.   Windows,
  12. {$ELSE}
  13.   WinTypes, WinProcs,
  14. {$ENDIF}
  15.   SysUtils, Classes, Dialogs, Forms, Controls, Graphics, TypInfo, Menus,
  16.   IvCommon;
  17.  
  18. const
  19.   IV_SUB_SEPARATOR_C  = ',';
  20.  
  21.   TEST_MASK_C = $01;
  22.   PURE_ASCII_MASK_C = $02;
  23.  
  24.   { Code pages }
  25.  
  26.   THAI_CP_C = 874;
  27.   JAPANESE_CP_C = 932;
  28.   SIMPLIFIED_CHINESE_CP_C = 936;
  29.   KOREAN_CP_C = 949;
  30.   KOREAN_JOHAB_CP_C = 1361;
  31.   TRADITIONAL_CHINESE_CP_C = 950;
  32.   EAST_EUROPE_CP_C = 1250;
  33.   CYRILLIC_CP_C = 1251;
  34.   WESTERN_CP_C = 1252;
  35.   GREEK_CP_C = 1253;
  36.   TURKISH_CP_C = 1254;
  37.   HEBREW_CP_C = 1255;
  38.   ARABIC_CP_C = 1256;
  39.   BALTIC_CP_C = 1257;
  40.   VIETNAMESE_CP_C = 1258;
  41.  
  42.   LOCALE_ILCID = 0;
  43.  
  44.   LOCALE_IPRIMARYLANGUAGE = 1024;
  45.   LOCALE_ISUBLANGUAGE = 1025;
  46.   LOCALE_SWIN16LANGUAGENAME = 1026;
  47.   LOCALE_SWIN16COUNTRYNAME = 1027;
  48.   LOCALE_SISOLANGUAGE = 1028;
  49.   LOCALE_SISOCOUNTRY = 1029;
  50.  
  51.   LANG_USER   = -1;
  52.   LANG_SYSTEM = -2;
  53.  
  54.   SUBLANG_FINNISH        = $01;    { Finnish }
  55.   SUBLANG_FINNISH_SWEDEN = $02;    { Finnish (Sweden) }
  56.  
  57. {$IFDEF IVANSI}
  58.   { These were missing in Delphi 2.0's and C++Builder 1.0's Windows unit }
  59.  
  60.   LANG_ARABIC      = $01;
  61.   LANG_FARSI       = $29;
  62.   LANG_HEBREW      = $0d;
  63.   LANG_INDONESIAN  = $21;
  64.   LANG_SERBIAN     = $1a;
  65.   LANG_THAI        = $1e;
  66.   LANG_VIETNAMESE  = $2a;
  67.  
  68.   LANG_ALBANIAN    = $1c;
  69.   LANG_BELARUSIAN  = $23;
  70.   LANG_UKRAINIAN   = $22;
  71.   LANG_ESTONIAN    = $25;
  72.   LANG_LATVIAN     = $26;
  73.   LANG_LITHUANIAN  = $27;
  74.  
  75.   SUBLANG_ENGLISH_SOUTH_AFRICA         = $07;    { English (South Africa) }
  76.   SUBLANG_ENGLISH_JAMAICA              = $08;    { English (Jamaica) }
  77.   SUBLANG_ENGLISH_CARIBBEAN            = $09;    { English (Caribbean) }
  78.   SUBLANG_ENGLISH_BELIZE               = $0a;    { English (Belize) }
  79.   SUBLANG_ENGLISH_TRINIDAD             = $0b;    { English (Trinidad) }
  80.   SUBLANG_FRENCH_LUXEMBOURG            = $05;    { French (Luxembourg) }
  81.   SUBLANG_GERMAN_LUXEMBOURG            = $04;    { German (Luxembourg) }
  82.   SUBLANG_GERMAN_LIECHTENSTEIN         = $05;    { German (Liechtenstein) }
  83.   SUBLANG_KOREAN                       = $01;    { Korean (Extended Wansung) }
  84.   SUBLANG_KOREAN_JOHAB                 = $02;    { Korean (Johab) }
  85.   SUBLANG_SERBIAN_LATIN                = $02;
  86.   SUBLANG_SERBIAN_CYRILLIC             = $03;
  87.   SUBLANG_SPANISH_GUATEMALA            = $04;    { Spanish (Guatemala) }
  88.   SUBLANG_SPANISH_COSTA_RICA           = $05;    { Spanish (Costa Rica) }
  89.   SUBLANG_SPANISH_PANAMA               = $06;    { Spanish (Panama) }
  90.   SUBLANG_SPANISH_DOMINICAN_REPUBLIC   = $07;    { Spanish (Dominican Republic) }
  91.   SUBLANG_SPANISH_VENEZUELA            = $08;    { Spanish (Venezuela) }
  92.   SUBLANG_SPANISH_COLOMBIA             = $09;    { Spanish (Colombia) }
  93.   SUBLANG_SPANISH_PERU                 = $0a;    { Spanish (Peru) }
  94.   SUBLANG_SPANISH_ARGENTINA            = $0b;    { Spanish (Argentina) }
  95.   SUBLANG_SPANISH_ECUADOR              = $0c;    { Spanish (Ecuador) }
  96.   SUBLANG_SPANISH_CHILE                = $0d;    { Spanish (Chile) }
  97.   SUBLANG_SPANISH_URUGUAY              = $0e;    { Spanish (Uruguay) }
  98.   SUBLANG_SPANISH_PARAGUAY             = $0f;    { Spanish (Paraguay) }
  99.   SUBLANG_SPANISH_BOLIVIA              = $10;    { Spanish (Bolivia) }
  100.   SUBLANG_SPANISH_EL_SALVADOR          = $11;    { Spanish (El Salvador) }
  101.   SUBLANG_SPANISH_HONDURAS             = $12;    { Spanish (Honduras) }
  102.   SUBLANG_SPANISH_NICARAGUA            = $13;    { Spanish (Nicaragua) }
  103.   SUBLANG_SPANISH_PUERTO_RICO          = $14;    { Spanish (Puerto Rico) }
  104.   SUBLANG_SWEDISH                      = $01;    { Swedish }
  105.   SUBLANG_SWEDISH_FINLAND              = $02;    { Swedish (Finland) }
  106.  
  107.   VIETNAMESE_CHARSET = 163;
  108.  
  109.   LOCALE_ITIMEMARKPOSN        = $00001005; { time marker position }
  110.   LOCALE_IDEFAULTANSICODEPAGE = $00001004; { default ansi code page }
  111.   LOCALE_ICALENDARTYPE        = $00001009; { type of calendar specifier }
  112.   LOCALE_IOPTIONALCALENDAR    = $0000100B; { additional calendar types specifier }
  113.   LOCALE_IFIRSTDAYOFWEEK      = $0000100C; { first day of week specifier }
  114.   LOCALE_IFIRSTWEEKOFYEAR     = $0000100D; { first week of year specifier }
  115.   LOCALE_FONTSIGNATURE        = $00000058; { font signature }
  116.   LOCALE_SISO639LANGNAME      = $00000059;
  117.   LOCALE_SISO3166CTRYNAME     = $0000005A;
  118. {$ENDIF}
  119.  
  120. {$IFNDEF WIN32}
  121.   { Win16 doesn't have NLSAPI. Multilizer emulates it. }
  122.  
  123.   LANG_NEUTRAL     = $00;
  124.  
  125.   LANG_AFRIKAANS   = $36;
  126.   LANG_ARABIC      = $01;
  127.   LANG_ALBANIAN    = $1c;
  128.   LANG_BASQUE      = $2d;
  129.   LANG_BELARUSIAN  = $23;
  130.   LANG_BULGARIAN   = $02;
  131.   LANG_CATALAN     = $03;
  132.   LANG_CHINESE     = $04;
  133.   LANG_CROATIAN    = $1a;
  134.   LANG_CZECH       = $05;
  135.   LANG_DANISH      = $06;
  136.   LANG_DUTCH       = $13;
  137.   LANG_ENGLISH     = $09;
  138.   LANG_ESTONIAN    = $25;
  139.   LANG_FAEROESE    = $38;
  140.   LANG_FARSI       = $29;
  141.   LANG_FINNISH     = $0b;
  142.   LANG_FRENCH      = $0c;
  143.   LANG_GERMAN      = $07;
  144.   LANG_GREEK       = $08;
  145.   LANG_HEBREW      = $0d;
  146.   LANG_HUNGARIAN   = $0e;
  147.   LANG_ICELANDIC   = $0f;
  148.   LANG_INDONESIAN  = $21;
  149.   LANG_ITALIAN     = $10;
  150.   LANG_JAPANESE    = $11;
  151.   LANG_KOREAN      = $12;
  152.   LANG_LATVIAN     = $26;
  153.   LANG_LITHUANIAN  = $27;
  154.   LANG_NORWEGIAN   = $14;
  155.   LANG_POLISH      = $15;
  156.   LANG_PORTUGUESE  = $16;
  157.   LANG_ROMANIAN    = $18;
  158.   LANG_RUSSIAN     = $19;
  159.   LANG_SERBIAN     = $1a;
  160.   LANG_SLOVAK      = $1b;
  161.   LANG_SLOVENIAN   = $24;
  162.   LANG_SPANISH     = $0a;
  163.   LANG_SWEDISH     = $1d;
  164.   LANG_THAI        = $1e;
  165.   LANG_TURKISH     = $1f;
  166.   LANG_UKRAINIAN   = $22;
  167.   LANG_VIETNAMESE  = $2a;
  168.  
  169.   SUBLANG_NEUTRAL              = $00;    { language neutral }
  170.   SUBLANG_DEFAULT              = $01;    { user default }
  171.   SUBLANG_SYS_DEFAULT          = $02;    { system default }
  172.  
  173.   SUBLANG_CHINESE_TRADITIONAL          = $01;    { Chinese (Taiwan) }
  174.   SUBLANG_CHINESE_SIMPLIFIED           = $02;    { Chinese (PR China) }
  175.   SUBLANG_CHINESE_HONGKONG             = $03;    { Chinese (Hong Kong) }
  176.   SUBLANG_CHINESE_SINGAPORE            = $04;    { Chinese (Singapore) }
  177.   SUBLANG_DUTCH                        = $01;    { Dutch }
  178.   SUBLANG_DUTCH_BELGIAN                = $02;    { Dutch (Belgian) }
  179.   SUBLANG_ENGLISH_US                   = $01;    { English (USA) }
  180.   SUBLANG_ENGLISH_UK                   = $02;    { English (UK) }
  181.   SUBLANG_ENGLISH_AUS                  = $03;    { English (Australian) }
  182.   SUBLANG_ENGLISH_CAN                  = $04;    { English (Canadian) }
  183.   SUBLANG_ENGLISH_NZ                   = $05;    { English (New Zealand) }
  184.   SUBLANG_ENGLISH_EIRE                 = $06;    { English (Irish) }
  185.   SUBLANG_ENGLISH_SOUTH_AFRICA         = $07;    { English (South Africa) }
  186.   SUBLANG_ENGLISH_JAMAICA              = $08;    { English (Jamaica) }
  187.   SUBLANG_ENGLISH_CARIBBEAN            = $09;    { English (Caribbean) }
  188.   SUBLANG_ENGLISH_BELIZE               = $0a;    { English (Belize) }
  189.   SUBLANG_ENGLISH_TRINIDAD             = $0b;    { English (Trinidad) }
  190.   SUBLANG_FRENCH                       = $01;    { French }
  191.   SUBLANG_FRENCH_BELGIAN               = $02;    { French (Belgian) }
  192.   SUBLANG_FRENCH_CANADIAN              = $03;    { French (Canadian) }
  193.   SUBLANG_FRENCH_SWISS                 = $04;    { French (Swiss) }
  194.   SUBLANG_FRENCH_LUXEMBOURG            = $05;    { French (Luxembourg) }
  195.   SUBLANG_GERMAN                       = $01;    { German }
  196.   SUBLANG_GERMAN_SWISS                 = $02;    { German (Swiss) }
  197.   SUBLANG_GERMAN_AUSTRIAN              = $03;    { German (Austrian) }
  198.   SUBLANG_GERMAN_LUXEMBOURG            = $04;    { German (Luxembourg) }
  199.   SUBLANG_GERMAN_LIECHTENSTEIN         = $05;    { German (Liechtenstein) }
  200.   SUBLANG_ITALIAN                      = $01;    { Italian }
  201.   SUBLANG_ITALIAN_SWISS                = $02;    { Italian (Swiss) }
  202.   SUBLANG_KOREAN                       = $01;    { Korean (Extended Wansung) }
  203.   SUBLANG_KOREAN_JOHAB                 = $02;    { Korean (Johab) }
  204.   SUBLANG_NORWEGIAN_BOKMAL             = $01;    { Norwegian (Bokmal) }
  205.   SUBLANG_NORWEGIAN_NYNORSK            = $02;    { Norwegian (Nynorsk) }
  206.   SUBLANG_PORTUGUESE                   = $02;    { Portuguese }
  207.   SUBLANG_PORTUGUESE_BRAZILIAN         = $01;    { Portuguese (Brazilian) }
  208.   SUBLANG_SERBIAN_LATIN                = $02;    { Serbian (Latin) }
  209.   SUBLANG_SERBIAN_CYRILLIC             = $03;    { Serbian (Cyrillic) }
  210.   SUBLANG_SPANISH                      = $01;    { Spanish (Castilian) }
  211.   SUBLANG_SPANISH_MEXICAN              = $02;    { Spanish (Mexican) }
  212.   SUBLANG_SPANISH_MODERN               = $03;    { Spanish (Modern) }
  213.   SUBLANG_SPANISH_GUATEMALA            = $04;    { Spanish (Guatemala) }
  214.   SUBLANG_SPANISH_COSTA_RICA           = $05;    { Spanish (Costa Rica) }
  215.   SUBLANG_SPANISH_PANAMA               = $06;    { Spanish (Panama) }
  216.   SUBLANG_SPANISH_DOMINICAN_REPUBLIC   = $07;    { Spanish (Dominican Republic) }
  217.   SUBLANG_SPANISH_VENEZUELA            = $08;    { Spanish (Venezuela) }
  218.   SUBLANG_SPANISH_COLOMBIA             = $09;    { Spanish (Colombia) }
  219.   SUBLANG_SPANISH_PERU                 = $0a;    { Spanish (Peru) }
  220.   SUBLANG_SPANISH_ARGENTINA            = $0b;    { Spanish (Argentina) }
  221.   SUBLANG_SPANISH_ECUADOR              = $0c;    { Spanish (Ecuador) }
  222.   SUBLANG_SPANISH_CHILE                = $0d;    { Spanish (Chile) }
  223.   SUBLANG_SPANISH_URUGUAY              = $0e;    { Spanish (Uruguay) }
  224.   SUBLANG_SPANISH_PARAGUAY             = $0f;    { Spanish (Paraguay) }
  225.   SUBLANG_SPANISH_BOLIVIA              = $10;    { Spanish (Bolivia) }
  226.   SUBLANG_SPANISH_EL_SALVADOR          = $11;    { Spanish (El Salvador) }
  227.   SUBLANG_SPANISH_HONDURAS             = $12;    { Spanish (Honduras) }
  228.   SUBLANG_SPANISH_NICARAGUA            = $13;    { Spanish (Nicaragua) }
  229.   SUBLANG_SPANISH_PUERTO_RICO          = $14;    { Spanish (Puerto Rico) }
  230.   SUBLANG_SWEDISH                      = $01;    { Swedish }
  231.   SUBLANG_SWEDISH_FINLAND              = $02;    { Swedish (Finland) }
  232.  
  233.   SORT_DEFAULT = $0 ; { sorting default }
  234.   LOCALE_SENGLANGUAGE = 4097; { English name of language }
  235.   LOCALE_SNATIVELANGNAME = 4; { native name of language }
  236.   LOCALE_SENGCOUNTRY = 4098; { English name of country }
  237.   LOCALE_SNATIVECTRYNAME = 8; { native name of country }
  238.   LOCALE_IDEFAULTANSICODEPAGE = $00001004; { default ansi code page }
  239.   LOCALE_IMEASURE = 13; { 0 = metric, 1 = US }
  240.   LOCALE_SDECIMAL = 14; { decimal separator }
  241.   LOCALE_STHOUSAND = 15; { thousand separator }
  242.   LOCALE_SCURRENCY = 20; { local monetary symbol }
  243.   LOCALE_ICURRDIGITS = 25; { # local monetary digits }
  244.   LOCALE_ICURRENCY = 27; { positive currency mode }
  245.   LOCALE_INEGCURR = 28; { negative currency mode }
  246.   LOCALE_SDATE = 29; { date separator }
  247.   LOCALE_STIME = 30; { time separator }
  248.   LOCALE_SSHORTDATE = 31; { short date format string }
  249.   LOCALE_SLONGDATE = $20; { long date format string }
  250.   LOCALE_ITIME = 35; { time format specifier }
  251.   LOCALE_ITIMEMARKPOSN = $00001005; { time marker position }
  252.   LOCALE_ITLZERO = 37; { leading zeros in time field }
  253.   LOCALE_S1159 = 40; { AM designator }
  254.   LOCALE_S2359 = 41; { PM designator }
  255.   LOCALE_SDAYNAME1 = 42; { long name for Monday }
  256.   LOCALE_SDAYNAME7 = 48; { long name for Sunday }
  257.   LOCALE_SABBREVDAYNAME1 = 49; { abbreviated name for Monday }
  258.   LOCALE_SABBREVDAYNAME7 = 55; { abbreviated name for Sunday }
  259.   LOCALE_SMONTHNAME1 = 56; { long name for January }
  260.   LOCALE_SMONTHNAME12 = 67; { long name for December }
  261.   LOCALE_SABBREVMONTHNAME1 = 68; { abbreviated name for January }
  262.   LOCALE_SABBREVMONTHNAME12 = 79; { abbreviated name for December }
  263.   LOCALE_STIMEFORMAT = 4099; { time format string }
  264.   LOCALE_ICALENDARTYPE        = $00001009; { type of calendar specifier }
  265.   LOCALE_IOPTIONALCALENDAR    = $0000100B; { additional calendar types specifier }
  266.   LOCALE_IFIRSTDAYOFWEEK      = $0000100C; { first day of week specifier }
  267.   LOCALE_IFIRSTWEEKOFYEAR     = $0000100D; { first week of year specifier }
  268.   LOCALE_SISO639LANGNAME = $00000059;
  269.   LOCALE_SISO3166CTRYNAME = $0000005A;
  270.  
  271.   CAL_GREGORIAN = 1;     { Gregorian (localized) calendar }
  272.   CAL_GREGORIAN_US = 2;  { Gregorian (U.S.) calendar }
  273. {$ENDIF}
  274.  
  275. {$IFDEF WIN32}
  276.   {$IFDEF IVVB}
  277.   KEY_C = VB_KEY_C;
  278.   {$ELSE}
  279.     {$IFDEF VER90}
  280.   KEY_C = DELPHI2_KEY_C;
  281.     {$ELSE}
  282.       {$IFDEF VER100}
  283.   KEY_C = DELPHI3_KEY_C;
  284.       {$ELSE}
  285.         {$IFDEF VER93}
  286.   KEY_C = CBUILDER1_KEY_C;
  287.         {$ELSE}
  288.           {$IFDEF VER110}
  289.   KEY_C = CBUILDER3_KEY_C;
  290.           {$ELSE}
  291.             {$IFDEF VER120}
  292.   KEY_C = DELPHI4_KEY_C;
  293.             {$ELSE}
  294.               {$IFDEF VER125}
  295.   KEY_C = CBUILDER4_KEY_C;
  296.               {$ELSE}
  297.   KEY_C = DELPHI5_KEY_C;
  298.               {$ENDIF}
  299.             {$ENDIF}
  300.           {$ENDIF}
  301.         {$ENDIF}
  302.       {$ENDIF}
  303.     {$ENDIF}
  304.   {$ENDIF}
  305. {$ELSE}
  306.   KEY_C = '';
  307. {$ENDIF}
  308.  
  309. {$IFDEF IVVB}
  310.   SECTION_C = VB16_SECTION_C;
  311. {$ELSE}
  312.   SECTION_C = DELPHI1_SECTION_C;
  313. {$ENDIF}
  314.  
  315.   CONTEXT_SEPARATOR_C = #127;
  316.   EURO_CHAR_C = #128;
  317.  
  318. type
  319. {$IFDEF WIN32}
  320.   TIvString = AnsiString;
  321.   {$IFDEF IVWIDE}
  322.   TIvWideString = WideString;
  323.   {$ELSE}
  324.   TIvWideString = PWideChar;
  325.   {$ENDIF}
  326. {$ELSE}
  327.   TIvString = PChar;
  328. {$ENDIF}
  329.  
  330.   TIvByteOrder = (ivboBigEndian, ivboLittleEndian);
  331.   TIvCharacterSet = (ivcsUnicode, ivcsCodePage);
  332.  
  333.   TIvDialogPosition = (ivdpParent, ivdpCenter);
  334.   TIvDialogPositions = set of TIvDialogPosition;
  335.  
  336. {$IFDEF IVANSI}
  337.   { This was missing in Delphi 2.0's windows unit }
  338.  
  339.   TFontCharset = 0..255;
  340. {$ENDIF}
  341.  
  342. {$IFDEF WIN32}
  343.   PHLK = ^HKL;
  344.  
  345.   TIvCharsetInfo = record
  346.     charSet: TFontCharset;
  347.     codePage: Integer;
  348.   end;
  349.  
  350.   PLocaleFontSignature = ^TLocaleFontSignature;
  351.   TLocaleFontSignature = packed record
  352.     fsUsb: array[0..3] of DWORD;
  353.     fsCsbDefault: array[0..1] of DWORD;
  354.     fsCsbSupported: array[0..1] of DWORD;
  355.   end;
  356.  
  357.   TIvFontCharset = (ivcsDefault, ivcsOEM, ivcsSymbol, ivcsMac, ivcsAnsi,
  358.     ivcsEastEurope, ivcsBaltic, ivcsRussian, ivcsGreek, ivcsTurkish,
  359.     ivcsArabic, ivcsHebrew, ivcsShiftJIS, ivcsHangeul, ivcsJohab,
  360.     ivcsChineseBig5, ivcsGB2312, ivcsThai, ivcsVietnamese);
  361.   TIvFontCharsets = set of TIvFontCharset;
  362. {$ENDIF}
  363.  
  364.   { TIvPropInfoList }
  365.  
  366.   TIvPropInfoList = class
  367.   private
  368. {$IFDEF VER125}
  369.     FList: Pointer;
  370. {$ELSE}
  371.     FList: PPropList;
  372. {$ENDIF}
  373.     FCount: Integer;
  374.     FSize: Integer;
  375.  
  376.     function Get(Index: Integer): PPropInfo;
  377.  
  378.   public
  379.     constructor Create(obj: TObject; Filter: TTypeKinds);
  380.     destructor Destroy; override;
  381.  
  382.     property Count: Integer read FCount;
  383.     property Items[Index: Integer]: PPropInfo read Get; default;
  384.   end;
  385.  
  386.   { TIvLanguage }
  387.  
  388.   TIvLanguageOption = (ivloTest, ivloPureASCII);
  389.   TIvLanguageOptions = set of TIvLanguageOption;
  390.   TIvCharacterSetType = (ivcsSingleByte, ivcsMultiByte, ivcsBiDirectional);
  391.  
  392.   TIvDisplayName = (ivdnEnglish, ivdnNative, ivdnTranslated);
  393.  
  394.   TIvDictionary = class;
  395.  
  396.   TIvLanguage = class(TObject)
  397.   protected
  398.     FCodePage: Integer;
  399.     FPrimary: Integer;
  400.     FVariant: String;
  401.     FActiveSub: Integer;
  402.     FDefaultSub: Integer;
  403.     FSubs: TStringList;
  404.     FISOLanguage: String;
  405.     FISODefaultCountry: String;
  406.     FISOCountries: TStringList;
  407.     FEnglishName: String;
  408.     FNativeName: String;
  409.     FFontName: String;
  410.     FFontSize: Integer;
  411.     FOptions: TIvLanguageOptions;
  412. {$IFDEF WIN32}
  413.     FCharset: TFontCharset;
  414. {$ENDIF}
  415.  
  416.     function GetSub: Integer;
  417.     function GetSubCount: Integer;
  418.     function GetSubs(i: Integer): Integer;
  419.  
  420.     function GetAllSubs: String;
  421.     procedure SetAllSubs(const value: String);
  422.  
  423.     function GetISOCountry: String;
  424.     function GetISOCountryCount: Integer;
  425.     function GetISOCountries(i: Integer): String;
  426.  
  427.     function GetISOAllCountries: String;
  428.     procedure SetISOAllCountries(const value: String);
  429.  
  430.     function GetLocale: Integer;
  431.     function GetLangId: Integer;
  432.     function GetDefaultLocale: Integer;
  433.     function GetActiveLocale: Integer;
  434.     function GetCharsetType: TIvCharacterSetType;
  435.  
  436.     procedure SetActiveSub(value: Integer);
  437.  
  438.     procedure SetCodePage(value: Integer);
  439.  
  440.     function GetOptionsAsInt: Integer;
  441.     procedure SetOptionsAsInt(value: Integer);
  442.  
  443.   public
  444.     constructor Create;
  445.     constructor CreateValue(
  446.       primary, defaultSub, codePage: Integer;
  447.       const subs, englishName, nativeName, fontName: String;
  448.       fontSize: Integer;
  449.       options: TIvLanguageOptions);
  450.     destructor Destroy; override;
  451.  
  452.     procedure Assign(source: TIvLanguage); virtual;
  453.     function Copy: TIvLanguage; virtual;
  454.     procedure Init; virtual;
  455.  
  456.     function PrimaryEquals(language: TIvLanguage): Boolean; virtual;
  457.  
  458.     function GetBundleExtension: String;
  459.  
  460.     procedure ClearSubs;
  461.     procedure AddSub(sub: Integer);
  462.  
  463.     procedure ClearISOCountries;
  464.     procedure AddISOCountry(country: String);
  465.  
  466.     function GetDisplayName(
  467.       displayName: TIvDisplayName;
  468.       dictionary: TIvDictionary): String; virtual;
  469.  
  470.     class function SubStrToSubId(const str: String): Integer;
  471.  
  472.     property Sub: Integer read GetSub;
  473.     property SubCount: Integer read GetSubCount;
  474.     property Subs[i: Integer]: Integer read GetSubs;
  475.     property ISOCountry: String read GetISOCountry;
  476.     property ISOCountryCount: Integer read GetISOCountryCount;
  477.     property ISOCountries[i: Integer]: String read GetISOCountries;
  478. {$IFDEF IVVB}
  479.     property VBSubs: TStringList read FSubs;
  480.     property VBISOCountries: TStringList read FISOCountries;
  481. {$ENDIF}
  482.     property LangId: Integer read GetLangId;
  483.     property Locale: Integer read GetLocale;
  484.     property DefaultLocale: Integer read GetDefaultLocale;
  485.     property ActiveLocale: Integer read GetActiveLocale;
  486.     property CharsetType: TIvCharacterSetType read GetCharsetType;
  487.     property EnglishName: String read FEnglishName write FEnglishName;
  488.     property NativeName: String read FNativeName write FNativeName;
  489. {$IFDEF WIN32}
  490.     property Charset: TFontCharset read FCharset write FCharset;
  491. {$ENDIF}
  492.     property CodePage: Integer read FCodePage write SetCodePage;
  493.     property Primary: Integer read FPrimary write FPrimary;
  494.     property Variant: String read FVariant write FVariant;
  495.     property AllSubs: String read GetAllSubs write SetAllSubs;
  496.     property DefaultSub: Integer read FDefaultSub write FDefaultSub;
  497.     property ActiveSub: Integer read FActiveSub write SetActiveSub;
  498.     property ISOLanguage: String read FISOLanguage write FISOLanguage;
  499.     property ISOAllCountries: String read GetISOAllCountries write SetISOAllCountries;
  500.     property ISODefaultCountry: String read FISODefaultCountry write FISODefaultCountry;
  501.     property FontName: String read FFontName write FFontName;
  502.     property FontSize: Integer read FFontSize write FFontSize;
  503.     property Options: TIvLanguageOptions read FOptions write FOptions;
  504.     property OptionsAsInt: Integer read GetOptionsAsInt write SetOptionsAsInt;
  505.   end;
  506.  
  507.   { TIvLocale }
  508.  
  509.   TIvMeasurementSystem = (ivmsMetric, ivmsUS);
  510.  
  511.   TIvCurrencyFormat = (ivcfS1, ivcf1S, ivcfS_1, ivcf1_S);
  512.  
  513.   TIvNegativeCurrencyFormat = (ivncS1, ivncNS1, ivncSN1, ivncS1N, ivnc1S,
  514.     ivncN1S, ivnc1NS, ivnc1SN, ivncN1_S, ivncNS_1, ivnc1_SN, ivncS_1N,
  515.     ivncS_N1, ivnc1N_S, ivncS_1, ivnc1_S);
  516.  
  517.   TIvTimeFormat = (ivtf12, ivtf24);
  518.   TIvTimeMarkPosition = (ivtmSuffix, ivtmPrefix);
  519.  
  520.   TIvDayOfWeek = (ivwdMonday, ivwdTuesday, ivwdWednesday, ivwdThursday, ivwdFriday, ivwdSaturday, ivwdSunday);
  521.   TIvFirstWeekOfYear = (ivfwFirstPart, ivfwFirstFull, ivfwFirst4);
  522.  
  523.   TIvCalendarType = (ivctNone, ivctGregorian, ivctGregorianUS, ivctJapan,
  524.     ivctTaiwan, ivctKorea, ivctHijri, ivctThai, ivctHebrew);
  525.  
  526.   TIvEuro = (iveNormal, iveBusiness, iveIgnore);
  527.   TIvEMU = (iveNone, iveLocal, iveLocalAndEuro, iveEuroAndLocal, iveEuro);
  528.  
  529.   TIvLocale = class(TObject)
  530.   private
  531.     function GetLangId: Integer;
  532.     procedure SetLangId(value: Integer);
  533.  
  534.     function GetLocale: Integer;
  535.     procedure SetLocale(value: Integer);
  536.     function GetCharsetType: TIvCharacterSetType;
  537.     function GetEMU: TIvEMU;
  538.     function GetEMUCurrencyString: String;
  539.  
  540.   public
  541.     Primary: Integer;
  542.     Sub: Integer;
  543.     SortId: Integer;
  544.     ISOLanguage: String;
  545.     ISOCountry: String;
  546.     CodePage: Integer;
  547.     IsCustom: Boolean;
  548. {$IFDEF WIN32}
  549.     Charset: TFontCharset;
  550. {$ENDIF}
  551.  
  552.     EnglishLanguageName: String;
  553.     EnglishCountryName: String;
  554.     NativeLanguageName: String;
  555.     NativeCountryName: String;
  556.     Win16LanguageName: String;
  557.     Win16CountryName: String;
  558.  
  559.     CurrencyString: String;
  560.     CurrencyFormat: TIvCurrencyFormat;
  561.     NegCurrFormat: TIvNegativeCurrencyFormat;
  562.     CurrencyDecimals: Byte;
  563.  
  564.     ThousandSeparator: Char;
  565.     DecimalSeparator: Char;
  566.  
  567.     DateSeparator: Char;
  568.     ShortDateFormat: String;
  569.     LongDateFormat: String;
  570.  
  571.     TimeSeparator: Char;
  572.     TimeAMString: String;
  573.     TimePMString: String;
  574.     TimeLeadingZeros: Boolean;
  575.     TimeFormat: TIvTimeFormat;
  576.     TimeMarkPosition: TIvTimeMarkPosition;
  577.  
  578.     MeasurementSystem: TIvMeasurementSystem;
  579.     CalendarType: TIvCalendarType;
  580.     OptionalCalendarType: TIvCalendarType;
  581.     FirstDayOfWeek: TIvDayOfWeek;
  582.     FirstWeekOfYear: TIvFirstWeekOfYear;
  583.  
  584.     ShortMonthNames: array[1..12] of String;
  585.     LongMonthNames: array[1..12] of String;
  586.     ShortDayNames: array[1..7] of String;
  587.     LongDayNames: array[1..7] of String;
  588.  
  589.     procedure Assign(source: TIvLocale); virtual;
  590.     function Copy: TIvLocale; virtual;
  591.     procedure Init; virtual;
  592.  
  593.     function GetDisplayName(
  594.       displayName: TIvDisplayName;
  595.       dictionary: TIvDictionary): String; virtual;
  596.  
  597.     property LangId: Integer read GetLangId write SetLangId;
  598.     property Locale: Integer read GetLocale write SetLocale;
  599.     property CharsetType: TIvCharacterSetType read GetCharsetType;
  600.     property EMU: TIvEMU read GetEMU;
  601.     property EMUCurrencyString: String read GetEMUCurrencyString;
  602.   end;
  603.  
  604.   { TIvContext }
  605.  
  606.   TIvContextTypeItem = (ivctForm, ivctComponent);
  607.   TIvContextType = set of TIvContextTypeItem;
  608.  
  609.   TIvContextCode = (ivccFlat, ivccFull, ivccComponent, ivccForm);
  610.  
  611.   TIvContext = class(TObject)
  612.   private
  613.     FForm: String;
  614.     FComponent: String;
  615.  
  616.   public
  617.     constructor CreateValue(const form, component: String);
  618.  
  619.     procedure Clear;
  620.     procedure Assign(context: TIvContext);
  621.     function Equals(context: TIvContext): Boolean;
  622.  
  623.     class function ContextCodeToType(value: TIvContextCode): TIvContextType;
  624.     class function ContextTypeToCode(value: TIvContextType): TIvContextCode;
  625.  
  626.     property Form: String read FForm write FForm;
  627.     property Component: String read FComponent write FComponent;
  628.   end;
  629.  
  630.   { TIvTranslation }
  631.  
  632.   TIvTranslation = class(TObject)
  633.   protected
  634.     function GetKey: String;
  635.  
  636.   public
  637.     Str: String;
  638.     Form: String;
  639.     Component: String;
  640.     Current: String;
  641.     Exists: Boolean;
  642.  
  643.     constructor CreateValue(const str, form, component: String);
  644.  
  645.     class function ComposeKey(const str, form, component: String): String;
  646.  
  647.     property Key: String read GetKey;
  648.   end;
  649.  
  650.   { TIvDictionary }
  651.  
  652.   TIvCustomTranslator = class;
  653.  
  654.   EIvMulti = class(Exception);
  655.  
  656.   TIvLanguageDialogOption = (ivloShowAllLanguages, ivloUseNativeLanguage, ivloNoCenter);
  657.   TIvLanguageDialogOptions = set of TIvLanguageDialogOption;
  658.  
  659.   TIvDictionaryOption = (ivdoUpdateLocaleVariables, ivdoAutoTranslate, ivdoYear2000, ivdoTranslateResourceStrings);
  660.   TIvDictionaryOptions = set of TIvDictionaryOption;
  661.  
  662.   TIvMissingTranslation = (ivmtUseNative, ivmtUseNull, ivmtTagNative, ivmtRaiseException);
  663.  
  664.   TIvBinding = (ivbiNone, ivbiLocaleToLanguage, ivbiLanguageToLocale);
  665.  
  666. {$IFDEF WIN32}
  667.   TIvCheckLevel = (ivclNone, ivclSystem, ivclCodePage);
  668. {$ENDIF}
  669.  
  670.   TIvDictionaryFormat = (ivdfFlat, ivdfContext);
  671.   TIvTranslationMode = (ivtmSingle, ivtmMultiple);
  672.  
  673.   TIvDictionary = class(TComponent)
  674.   private
  675.     FDictionaryCode: Integer;
  676.     FOnLocaleChange: TNotifyEvent;
  677.     FOnLanguageChange: TNotifyEvent;
  678.  
  679.   protected
  680.     FEuro: TIvEuro;
  681.     FContextType: TIvContextType;
  682.     FDictionaryName: String;
  683.     FOpen: Boolean;
  684.     FLanguage: Integer;
  685.     FActiveLanguage: Integer;
  686.     FOriginalLanguage: Integer;
  687.     FLocale: Integer;
  688.     FActiveLocale: Integer;
  689.     FLanguageLocale: Integer;
  690.     FNativeLocale: Integer;
  691.     FOptions: TIvDictionaryOptions;
  692.     FMissingTranslation: TIvMissingTranslation;
  693.     FBinding: TIvBinding;
  694.     FTempLanguageData: TIvLanguage;
  695.     FLanguageData: TIvLanguage;
  696.     FTempLocaleData: TIvLocale;
  697.     FLocaleData: TIvLocale;
  698.     FTranslators: TList;
  699. {$IFDEF WIN32}
  700.     FCheckLevel: TIvCheckLevel;
  701. {$ENDIF}
  702.  
  703.     function GetContextCode: TIvContextCode;
  704.  
  705.     procedure SetDictionaryName(const value: String);
  706.  
  707.     function GetPrimaryLanguage: Integer;
  708.     procedure SetPrimaryLanguage(value: Integer);
  709.  
  710.     function GetSubLanguage: Integer;
  711.     procedure SetSubLanguage(value: Integer);
  712.  
  713.     procedure SetLocale(value: Integer);
  714.     procedure SetLanguage(value: Integer);
  715.  
  716.     function GetTranslatorCount: Integer;
  717.     function GetTranslator(i: Integer): TIvCustomTranslator;
  718.  
  719.     function GetLanguage(i: Integer): TIvLanguage;
  720.     function GetLocale(i: Integer): TIvLocale;
  721.  
  722.     procedure SetEuro(value: TIvEuro);
  723.  
  724.     procedure InitLanguage(language: Integer);
  725.     procedure InitLocale(locale: Integer);
  726.     function DecodeLocale(value: Integer): Integer;
  727.  
  728.     function GetDefaultLanguage: Integer;
  729.  
  730.     procedure UnbindTranslators;
  731.  
  732.     procedure ReadDictionaryCode(reader: TReader);
  733.     procedure WriteDictionaryCode(writer: TWriter);
  734.     procedure DefineProperties(filer: TFiler); override;
  735.  
  736.     { Implement these in your derived dictionaries }
  737.  
  738.     function GetLanguageCount: Integer; virtual; abstract;
  739.     procedure GetLanguageData(index: Integer; language: TIvLanguage); virtual; abstract;
  740.     function GetLocaleCount: Integer; virtual; abstract;
  741.     procedure GetLocaleData(index: Integer; locale: TIvLocale); virtual; abstract;
  742.  
  743.     { You might need to override this in your derived dictionaries }
  744.  
  745.     function GetTranslationCount: Integer; virtual;
  746.     procedure LanguageChanged(languageChanged, localeChanged: Boolean); virtual;
  747.  
  748.   public
  749.     constructor Create(owner: TComponent); override;
  750.     destructor Destroy; override;
  751.  
  752.     { Implement these in your derived dictionaries }
  753.  
  754.     function TranslateContextString(
  755.       const str, form, component: String;
  756.       var translation: String): Boolean; virtual; abstract;
  757.  
  758.     { You might need to override these in your derived dictionaries }
  759.  
  760.     procedure Open; virtual;
  761.     procedure Close; virtual;
  762.     function CanBeOpened: Boolean; virtual;
  763.     procedure GetLanguageDatas(list: TList); virtual;
  764.     procedure GetLocaleDatas(list: TList); virtual;
  765.     function TranslateString(
  766.       const str: String;
  767.       var translation: String): Boolean; virtual;
  768.  
  769.     { If your dictionary support multiple translation, override these in your
  770.       derived dictionaries }
  771.  
  772.     procedure TranslateStrings(translations: TList); virtual;
  773.     function GetTranslationMode: TIvTranslationMode; virtual;
  774.  
  775.     function CheckTranslation(
  776.       const native, translation: String;
  777.       ok: Boolean): String;
  778.  
  779.     procedure AddTranslator(translator: TIvCustomTranslator);
  780.     procedure RemoveTranslator(translator: TIvCustomTranslator);
  781.  
  782.     procedure GetLocales(locales: TList);
  783.     procedure GetLocaleIds(locales: TList);
  784. {$IFDEF WIN32}
  785.     class procedure GetSystemLocales(locales: TList);
  786.     class procedure GetSystemLocaleIds(locales: TList);
  787.     class function GetSystemLocaleData(id: Integer; locale: TIvLocale): Boolean;
  788. {$ENDIF}
  789.     class procedure FreeList(list: TList);
  790.  
  791.     function GetLocaleDataById(id: Integer; locale: TIvLocale): Boolean;
  792.     function LocaleToLanguage(locale: Integer): Integer;
  793.  
  794.     function DoesTranslationExist(const str: String): Boolean;
  795.     function DoesContextTranslationExist(const str, form, component: String): Boolean;
  796.  
  797.     function Translate(const str: String): String;
  798.     function TranslateContext(const str, form, component: String): String;
  799.  
  800.     procedure TranslateWindow(wnd: THandle; str: String; resize: Boolean);
  801.  
  802.     function IsOpen: Boolean;
  803.  
  804.     procedure SynchronizeLocale; virtual;
  805.     procedure SynchronizeLanguage; virtual;
  806.  
  807.     procedure GetPrimaryLanguages(primaries: TStrings; native: Boolean); virtual;
  808.     procedure GetSubLanguages(language: TIvLanguage; subs: TStrings; native: Boolean);
  809.  
  810.     function IsLocaleSupported(locale: Integer): Boolean; virtual;
  811.  
  812. {$IFDEF IVWIDE}
  813.     class procedure HandleException(sender: TObject; e: Exception);
  814. {$ENDIF}
  815.  
  816.     class function IvCompareText(
  817.       const s1, s2: String;
  818.       locale: Integer;
  819.       ignoreSymbols: Boolean): Integer;
  820.     class function IvCompareStr(
  821.       const s1, s2: String;
  822.       locale: Integer;
  823.       ignoreSymbols: Boolean): Integer;
  824.     class function IvCompareBinary(const s1, s2: String): Integer;
  825.  
  826. {$IFDEF WIN32}
  827.     class function GetCompareOptions(ignoreCase, ignoreSymbols: Boolean): Integer;
  828. {$ENDIF}
  829.  
  830. {$IFDEF IVWIDE}
  831.     class function IvWideCompareText(
  832.       const s1, s2: WideString;
  833.       locale: Integer;
  834.       ignoreSymbols: Boolean): Integer;
  835.     class function IvWideCompareStr(
  836.       const s1, s2: WideString;
  837.       locale: Integer;
  838.       ignoreSymbols: Boolean): Integer;
  839.     class function IvWideCompareBinary(const s1, s2: WideString): Integer;
  840. {$ENDIF}
  841.  
  842. {$IFDEF WIN32}
  843.     class function IsLanguageSupportedBySystem(language: TIvLanguage): Boolean;
  844.     class function IsLanguageSupportedByCodePage(language: TIvLanguage): Boolean;
  845.  
  846.     class function IsLocaleSupportedBySystem(locale: TIvLocale): Boolean;
  847.     class function IsLocaleSupportedByCodePage(locale: TIvLocale): Boolean;
  848.  
  849.     function CompareText(const s1, s2: String): Integer;
  850.     function CompareStr(const s1, s2: String): Integer;
  851. {$ELSE}
  852.     function GetSystemDefaultLCID: Integer;
  853.     function GetUserDefaultLCID: Integer;
  854. {$ENDIF}
  855.  
  856.     class function ComposeLanguageName(
  857.       language: String;
  858.       primary, codePage: Integer;
  859.       translate: Boolean;
  860.       dictionary: TIvDictionary): String;
  861.  
  862.     class function ComposeCountryName(
  863.       country: String;
  864.       primary, sub: Integer;
  865.       translate: Boolean;
  866.       dictionary: TIvDictionary): String;
  867.  
  868.     class function ComposeLocaleName(
  869.       language, country: String;
  870.       primary, sub, codePage: Integer;
  871.       translate: Boolean;
  872.       dictionary: TIvDictionary): String;
  873.  
  874.     class procedure SetTimeFormats(
  875.       format: TIvTimeFormat;
  876.       markPosition: TIvTimeMarkPosition;
  877.       leadingZeros: Boolean;
  878.       var shortTimeFormat, longTimeFormat: String);
  879.  
  880.     class function TranslateDateFormat(const formatStr: String): String;
  881.  
  882.     function IsDesignTime: Boolean;
  883.  
  884.     property NativeLocale: Integer read FNativeLocale;
  885.     property ContextType: TIvContextType read FContextType;
  886.     property ContextCode: TIvContextCode read GetContextCode;
  887.     property ActiveLanguage: Integer read FActiveLanguage;
  888.     property LanguageLocale: Integer read FLanguageLocale;
  889.     property DefaultLanguage: Integer read GetDefaultLanguage;
  890.     property TranslationCount: Integer read GetTranslationCount;
  891.     property LanguageCount: Integer read GetLanguageCount;
  892.     property Languages[i: Integer]: TIvLanguage read GetLanguage;
  893.     property LanguageData: TIvLanguage read FLanguageData;
  894.     property LocaleCount: Integer read GetLocaleCount;
  895.     property Locales[i: Integer]: TIvLocale read GetLocale;
  896.     property LocaleData: TIvLocale read FLocaleData;
  897.     property TranslatorCount: Integer read GetTranslatorCount;
  898.     property Translators[i: Integer]: TIvCustomTranslator read GetTranslator;
  899.     property Locale: Integer read FActiveLocale write SetLocale;
  900.  
  901.   published
  902.     property DictionaryName: String read FDictionaryName write SetDictionaryName;
  903.     property PrimaryLanguage: Integer read GetPrimaryLanguage write SetPrimaryLanguage default LANG_NEUTRAL;
  904.     property SubLanguage: Integer read GetSubLanguage write SetSubLanguage default SUBLANG_DEFAULT;
  905.     property Language: Integer read FLanguage write SetLanguage default LANG_USER;
  906.     property Binding: TIvBinding read FBinding write FBinding default ivbiLocaleToLanguage;
  907.     property Options: TIvDictionaryOptions read FOptions write FOptions
  908.       default [ivdoUpdateLocaleVariables, ivdoAutoTranslate, ivdoYear2000, ivdoTranslateResourceStrings];
  909.     property MissingTranslation: TIvMissingTranslation read FMissingTranslation write FMissingTranslation
  910.       default ivmtUseNative;
  911.     property Euro: TIvEuro read FEuro write SetEuro default iveNormal;
  912. {$IFDEF WIN32}
  913.     property CheckLevel: TIvCheckLevel read FCheckLevel write FCheckLevel default ivclCodePage;
  914. {$ENDIF}
  915.     property OnLanguageChange: TNotifyEvent read FOnLanguageChange write FOnLanguageChange;
  916.     property OnLocaleChange: TNotifyEvent read FOnLocaleChange write FOnLocaleChange;
  917.   end;
  918.  
  919.   TIvDictionaries = class(TObject)
  920.   private
  921.     FItems: TList;
  922.  
  923.     function GetCount: Integer;
  924.     function GetItems(index: Integer): TIvDictionary;
  925.  
  926.     procedure Add(item: TIvDictionary);
  927.     procedure Remove(item: TIvDictionary);
  928.  
  929.   public
  930.     constructor Create;
  931.     destructor Destroy; override;
  932.  
  933.     function FindDictionary(const name: String): TIvDictionary;
  934.  
  935.     property Count: Integer read GetCount;
  936.     property Items[index: Integer]: TIvDictionary read GetItems; default;
  937.   end;
  938.  
  939.   { TIvTranslator }
  940.  
  941.   TIvTranslateEvent = procedure(translator: TIvCustomTranslator) of object;
  942.  
  943.   TIvTranslatorStateValue = (ivtsBound, ivtsScaled, ivtsMirrored, ivtsPreScanning);
  944.   TIvTranslatorState = set of TIvTranslatorStateValue;
  945.  
  946.   TIvCustomTranslator = class(TComponent)
  947.   protected
  948.     FTranslations: TList;
  949.     FState: TIvTranslatorState;
  950.     FDictionary: TIvDictionary;
  951.     FDictionaryName: String;
  952.     FOnBeforeTranslate: TIvTranslateEvent;
  953.     FOnAfterTranslate: TIvTranslateEvent;
  954.     FOnLocaleChange: TNotifyEvent;
  955.     FOnLanguageChange: TNotifyEvent;
  956.  
  957.     procedure ClearTranslations;
  958.  
  959.     procedure SetDictionary(value: TIvDictionary);
  960.     procedure SetDictionaryName(const value: String);
  961.  
  962. {$IFDEF WIN32}
  963.     procedure TranslateSystemMenu(handle: THandle; mdi: Boolean);
  964.     function GetSystemMenuWinHandle: THandle; virtual;
  965. {$ENDIF}
  966.  
  967.     procedure TranslateHost; virtual;
  968.  
  969.     function IsDesignTime: Boolean;
  970.  
  971.     procedure LanguageChanged(languageChanged, localeChanged: Boolean); virtual;
  972.  
  973.   public
  974.     constructor Create(owner: TComponent); override;
  975.     destructor Destroy; override;
  976.  
  977.     procedure Translate; virtual;
  978.     procedure Unbind; virtual;
  979.     procedure UnbindAndSetNative; virtual;
  980.  
  981.     property State: TIvTranslatorState read FState;
  982.     property Dictionary: TIvDictionary read FDictionary write SetDictionary;
  983.  
  984.   published
  985.     property DictionaryName: String read FDictionaryName write SetDictionaryName;
  986.     property OnBeforeTranslate: TIvTranslateEvent read FOnBeforeTranslate write FOnBeforeTranslate;
  987.     property OnAfterTranslate: TIvTranslateEvent read FOnAfterTranslate write FOnAfterTranslate;
  988.     property OnLocaleChange: TNotifyEvent read FOnLocaleChange write FOnLocaleChange;
  989.     property OnLanguageChange: TNotifyEvent read FOnLanguageChange write FOnLanguageChange;
  990.   end;
  991.  
  992. function GetMLRegistryValue(const valueName, defaultValue: String): String;
  993.  
  994. { Translation functions}
  995.  
  996. function Translate(const str: String): String;
  997. function TranslateContext(const str, form, component: String): String;
  998. function GetDefaultDictionary: TIvDictionary;
  999.  
  1000. { Multilingual functions }
  1001.  
  1002. {$IFDEF IVWIDE}
  1003. function MlFormat(const format: String; const args: array of const): String;
  1004. procedure MlShowMessage(const msg: string);
  1005. function MlMessageDlg(const msg: string; aType: TMsgDlgType; aButtons: TMsgDlgButtons; helpCtx: Longint): Word;
  1006. {$ENDIF}
  1007.  
  1008. { Locale functions }
  1009.  
  1010. function IvDoesLanguageRequirePro(primary: Integer): Boolean;
  1011. function IvDoesLanguageRequirePro32(primary: Integer): Boolean;
  1012. function IvMakeLangId(primaryLanguage, subLanguage: Integer): Integer;
  1013. function IvMakeLcId(langId, sortId: Integer): Integer;
  1014. function IvGetPrimaryFromLocale(locale: Integer): Integer;
  1015. function IvGetSubFromLocale(locale: Integer): Integer;
  1016.  
  1017. function IvLangIdToCodePage(langId: Integer): Integer;
  1018.  
  1019. { EMU functions }
  1020.  
  1021. function IsEMUMember(locale: Integer): Boolean;
  1022. function GetEMUPhase: TIvEMU;
  1023.  
  1024. {$IFDEF WIN32}
  1025. function IvWStrPCopy(dest: PWideChar; const source: TIvWideString): PWideChar;
  1026.  
  1027. function IvWStrToStr(const source: TIvWideString; codePage: Integer): String;
  1028. function IvStrToWStr(const source: String; codePage: Integer): TIvWideString;
  1029. function IvStrLen(const str: String; codePage: Integer): Integer;
  1030.  
  1031. function IvIsCodePageSupportedBySystem(codePage: Integer): Boolean;
  1032. function IvIsLocaleSupportedByCodePage(locale: Integer): Boolean;
  1033. function IvSetKeyboardLayout(langId: Integer): HKL;
  1034. function IvResetKeyboardLayout: HKL;
  1035. function IvGetCharsetInfo(langId: Integer): TIvCharsetInfo;
  1036. function IvCodePageToCharset(codePage: Integer): TFontCharset;
  1037. function IvLangIdToCharset(langId: Integer): TFontCharset;
  1038. function IvCharsetToCode(value: TIvFontCharset): Byte;
  1039. function IvCodeToCharset(value: Byte): TIvFontCharset;
  1040. function IvGetSupportedCharsets: TIvFontCharsets;
  1041. procedure IvGetFontNames(charsets: TIvFontCharsets; names: TStrings);
  1042. procedure IvGetFontNamesOfCharset(charset: Integer; names: TStrings);
  1043.  
  1044. function SysAllocString(P: PWideChar): PWideChar; stdcall;
  1045. function SysAllocStringLen(P: PWideChar; Len: Integer): PWideChar; stdcall;
  1046. function SysReAllocStringLen(var str: PWideChar; const P: PWideChar; Len: Integer): Integer; stdcall;
  1047. procedure SysFreeString(str: PWideChar); stdcall;
  1048. function SysStringLen(str: PWideChar): Integer; stdcall;
  1049. {$ENDIF}
  1050.  
  1051. function IvGetCharacterSetType(locale: Integer): TIvCharacterSetType;
  1052. function IvIsLocaleSingleByte(locale: Integer): Boolean;
  1053. function IvIsLocaleMultiByte(locale: Integer): Boolean;
  1054. function IvIsLocaleBidirectional(locale: Integer): Boolean;
  1055.  
  1056. {$IFDEF IVWIDE}
  1057. function TranslateLoadResString(resStringRec: PResStringRec): String;
  1058. function IvLoadResString(resStringRec: PResStringRec): String;
  1059.  
  1060. function TranslateShortCutToText(shortCut: TShortCut): String;
  1061. function IvShortCutToText(shortCut: TShortCut): String;
  1062. {$ENDIF}
  1063.  
  1064. var
  1065.   Dictionaries: TIvDictionaries;
  1066.  
  1067. {$IFDEF WIN32}
  1068.   KeyboardLayout: HKL;
  1069.   {$IFDEF IVANSI}
  1070.   commonWideString: PWideChar;
  1071.   {$ENDIF}
  1072.   {$IFDEF IVWIDE}
  1073.   resStrTranslationEnabled: Boolean;
  1074.   loadResStringChanged: Boolean;
  1075.   resStringBuffer: array[0..34] of Byte;
  1076.   shortCutBuffer: array[0..34] of Byte;
  1077.   {$ENDIF}
  1078. {$ENDIF}
  1079.  
  1080. implementation
  1081.  
  1082. uses
  1083. {$IFDEF WIN32}
  1084.   Registry,
  1085. {$ELSE}
  1086.   IniFiles,
  1087. {$ENDIF}
  1088. {$IFDEF IVVB}
  1089.   InnoOCX,
  1090. {$ENDIF}
  1091. {$IFDEF IVBINARY}
  1092.   IvStamp, IvDemoD,
  1093. {$ENDIF}
  1094.   Consts, Messages, IvParser;
  1095.  
  1096. {$IFDEF WIN32}
  1097. const
  1098.   CHARSET_COUNT_C = 32;
  1099.   CHARSETSET_TO_ID_C: array[0..CHARSET_COUNT_C - 1] of TIvCharsetInfo =
  1100.   (
  1101.     (charSet: ANSI_CHARSET; codePage: 1252),        { 0, Western Europe }
  1102.     (charSet: EASTEUROPE_CHARSET; codePage: 1250),  { 1, Eastern Europe }
  1103.     (charSet: RUSSIAN_CHARSET; codePage: 1251),     { 2, Cyrillic }
  1104.     (charSet: GREEK_CHARSET; codePage: 1253),       { 3, Greek }
  1105.     (charSet: TURKISH_CHARSET; codePage: 1254),     { 4, Turkish }
  1106.   {$IFDEF IVPRO}
  1107.     (charSet: HEBREW_CHARSET; codePage: 1255),      { 5, Hebrew }
  1108.     (charSet: ARABIC_CHARSET; codePage: 1256),      { 6, Arabic }
  1109.   {$ELSE}
  1110.     (charSet: 0; codePage: 0),
  1111.     (charSet: 0; codePage: 0),
  1112.   {$ENDIF}
  1113.     (charSet: BALTIC_CHARSET; codePage: 1257),      { 7, Baltic }
  1114.     (charSet: 0; codePage: 0),
  1115.     (charSet: 0; codePage: 0),
  1116.     (charSet: 0; codePage: 0),
  1117.     (charSet: 0; codePage: 0),
  1118.     (charSet: 0; codePage: 0),
  1119.     (charSet: 0; codePage: 0),
  1120.     (charSet: 0; codePage: 0),
  1121.     (charSet: 0; codePage: 0),
  1122.   {$IFDEF IVPRO}
  1123.     (charSet: THAI_CHARSET; codePage: 874),         { 16, Thai }
  1124.     (charSet: SHIFTJIS_CHARSET; codePage: 932),     { 17, Japanese }
  1125.     (charSet: GB2312_CHARSET; codePage: 936),       { 18, Chinese (Simplified) }
  1126.     (charSet: HANGEUL_CHARSET; codePage: 949),      { 19, Korean (Hangul) }
  1127.     (charSet: CHINESEBIG5_CHARSET; codePage: 950),  { 20, Chinese (Traditionel) }
  1128.     (charSet: JOHAB_CHARSET; codePage: 1361),       { 21, Korean (Johab) }
  1129.     (charSet: VIETNAMESE_CHARSET; codePage: 1258),  { 22, Vietnamese }
  1130.   {$ELSE}
  1131.     (charSet: 0; codePage: 0),
  1132.     (charSet: 0; codePage: 0),
  1133.     (charSet: 0; codePage: 0),
  1134.     (charSet: 0; codePage: 0),
  1135.     (charSet: 0; codePage: 0),
  1136.     (charSet: 0; codePage: 0),
  1137.     (charSet: 0; codePage: 0),
  1138.   {$ENDIF}
  1139.     (charSet: 0; codePage: 0),
  1140.     (charSet: 0; codePage: 0),
  1141.     (charSet: 0; codePage: 0),
  1142.     (charSet: 0; codePage: 0),
  1143.     (charSet: 0; codePage: 0),
  1144.     (charSet: 0; codePage: 0),
  1145.     (charSet: 0; codePage: 0),
  1146.     (charSet: 0; codePage: 0),
  1147.     (charSet: 0; codePage: 0)
  1148.   );
  1149. {$ENDIF}
  1150.  
  1151. var
  1152.   euroUsage: TIvEuro;
  1153. {$IFDEF WIN32}
  1154.   enumInteger: Integer;
  1155.   enumList: TList;
  1156.   supported: Boolean;
  1157. {$ELSE}
  1158.   userDefaultLCID: Integer;
  1159. {$ENDIF}
  1160.  
  1161. function GetMLRegistryValue(const valueName, defaultValue: String): String;
  1162. var
  1163. {$IFDEF WIN32}
  1164.   registry: TRegistry;
  1165. {$ELSE}
  1166.   iniFile: TIniFile;
  1167. {$ENDIF}
  1168. begin
  1169. {$IFDEF WIN32}
  1170.   registry := TRegistry.Create;
  1171.   try
  1172.     registry.RootKey := HKEY_LOCAL_MACHINE;
  1173.     if registry.OpenKey(KEY_C, False) and registry.ValueExists(valueName) then
  1174.       Result := registry.ReadString(valueName)
  1175.     else
  1176.       Result := defaultValue;
  1177.   finally
  1178.     registry.Free;
  1179.   end;
  1180. {$ELSE}
  1181.   iniFile := TIniFile.Create(INI_FILE_C);
  1182.   try
  1183.     Result := iniFile.ReadString(SECTION_C, valueName, defaultValue);
  1184.   finally
  1185.     iniFile.Free;
  1186.   end;
  1187. {$ENDIF}
  1188. end;
  1189.  
  1190.  
  1191. { TIvPropInfoList }
  1192.  
  1193. function GetPropList(typeInfo: PTypeInfo; typeKinds: TTypeKinds; propList: PPropList): Integer;
  1194. var
  1195.   i, count: Integer;
  1196.   propInfo: PPropInfo;
  1197.   tempList: PPropList;
  1198. begin
  1199.   Result := 0;
  1200.   count := GetTypeData(TypeInfo)^.PropCount;
  1201.   if count > 0 then
  1202.   begin
  1203.     GetMem(tempList, count * SizeOf(Pointer));
  1204.     try
  1205.       GetPropInfos(typeInfo, tempList);
  1206.       for i := 0 to Count - 1 do
  1207.       begin
  1208.         propInfo := tempList^[i];
  1209.         if (propInfo <> nil) and (propInfo^.PropType^.Kind in typeKinds) then
  1210.         begin
  1211.           if propList <> nil then
  1212.             propList^[Result] := propInfo;
  1213.           Inc(Result);
  1214.         end;
  1215.       end;
  1216.     finally
  1217.       FreeMem(TempList, count*SizeOf(Pointer));
  1218.     end;
  1219.   end;
  1220. end;
  1221.  
  1222. constructor TIvPropInfoList.Create(obj: TObject; Filter: TTypeKinds);
  1223. begin
  1224.   if obj.ClassInfo = nil then
  1225.   begin
  1226.     FCount:=0;
  1227.     FSize:=0;
  1228.   end
  1229.   else
  1230.   begin
  1231.     FCount := GetPropList(obj.ClassInfo, Filter, nil);
  1232.     FSize := FCount*SizeOf(Pointer);
  1233.     GetMem(FList, FSize);
  1234.     GetPropList(obj.ClassInfo, Filter, FList);
  1235.   end;
  1236. end;
  1237.  
  1238. destructor TIvPropInfoList.Destroy;
  1239. begin
  1240.   if FList <> nil then
  1241.     FreeMem(FList, FSize);
  1242. end;
  1243.  
  1244. function TIvPropInfoList.Get(Index: Integer): PPropInfo;
  1245. begin
  1246. {$IFDEF VER125}
  1247.   Result := PPropList(FList)^[Index];
  1248. {$ELSE}
  1249.   Result := FList^[Index];
  1250. {$ENDIF}
  1251. end;
  1252.  
  1253. {$IFDEF IVWIDE}
  1254. function MlFormat(const format: String; const args: array of const): String;
  1255. begin
  1256.   Result := SysUtils.Format(Translate(format), args);
  1257. end;
  1258.  
  1259. procedure MlShowMessage(const msg: string);
  1260. begin
  1261.   Dialogs.ShowMessage(Translate(msg));
  1262. end;
  1263.  
  1264. function MlMessageDlg(const msg: string; aType: TMsgDlgType; aButtons: TMsgDlgButtons; helpCtx: Longint): Word;
  1265. begin
  1266.   Result := Dialogs.MessageDlg(Translate(msg), aType, aButtons, helpCtx);
  1267. end;
  1268. {$ENDIF}
  1269.  
  1270. { TIvLanguage }
  1271.  
  1272. constructor TIvLanguage.Create;
  1273. begin
  1274.   CreateValue(0, 0, 0, '', '', '', '', 0, []);
  1275. end;
  1276.  
  1277. constructor TIvLanguage.CreateValue(
  1278.   primary, defaultSub, codePage: Integer;
  1279.   const subs, englishName, nativeName: String;
  1280.   const fontName: String;
  1281.   fontSize: Integer;
  1282.   options: TIvLanguageOptions);
  1283. begin
  1284.   inherited Create;
  1285.  
  1286.   FSubs := TStringList.Create;
  1287.   FISOCountries := TStringList.Create;
  1288.  
  1289.   FPrimary := primary;
  1290.   FDefaultSub := defaultSub;
  1291.   Self.CodePage := codePage;
  1292.   AllSubs := subs;
  1293.   FEnglishName := englishName;
  1294.   FNativeName := nativeName;
  1295.   FFontName := fontName;
  1296.   FFontSize := fontSize;
  1297.   FOptions := options;
  1298. end;
  1299.  
  1300. destructor TIvLanguage.Destroy;
  1301. begin
  1302.   FSubs.Free;
  1303.   FISOCountries.Free;
  1304.   inherited Destroy;
  1305. end;
  1306.  
  1307. procedure TIvLanguage.SetCodePage(value: Integer);
  1308. begin
  1309.   FCodePage := value;
  1310. {$IFDEF WIN32}
  1311.   if FCharset = 0 then
  1312.     FCharset := IvCodePageToCharset(FCodePage);
  1313. {$ENDIF}
  1314. end;
  1315.  
  1316. function TIvLanguage.PrimaryEquals(language: TIvLanguage): Boolean;
  1317. begin
  1318.   Result := (Primary = language.Primary) and (CodePage = language.CodePage);
  1319. end;
  1320.  
  1321. procedure TIvLanguage.Init;
  1322. begin
  1323.   { Old format used -1 as the fake. Now it is 0 }
  1324.  
  1325.   if FPrimary < 0 then
  1326.     FPrimary := LANG_NEUTRAL;
  1327.  
  1328.   if FPrimary = LANG_NEUTRAL then
  1329.   begin
  1330.     FDefaultSub := 0;
  1331.     FSubs.Clear;
  1332.     FOptions := [ivloPureASCII];
  1333.   end
  1334.   else
  1335.   begin
  1336.     { If the default sub of the language is negative or SUBLANG_NEUTRAL,
  1337.       SUBLANG_DEFAULT is used. If the language contains subs the first sub
  1338.       is used. }
  1339.  
  1340.     if FDefaultSub < SUBLANG_DEFAULT then
  1341.     begin
  1342.       FDefaultSub := SUBLANG_DEFAULT;
  1343.       if FSubs.Count > 0 then
  1344.         FDefaultSub := StrToInt(FSubs[0]);
  1345.     end;
  1346.   end;
  1347.  
  1348.   if FPrimary = LANG_NEUTRAL then
  1349.   begin
  1350.     EnglishName := 'Native';
  1351.     NativeName := 'Native';
  1352.   end
  1353.   else
  1354.   begin
  1355. {$IFDEF WIN32}
  1356.     if ISOLanguage = '' then
  1357.       ISOLanguage := GetLocaleStr(Locale, LOCALE_SISO639LANGNAME, '');
  1358.  
  1359.     if ISODefaultCountry = '' then
  1360.       ISODefaultCountry := GetLocaleStr(Locale, LOCALE_SISO3166CTRYNAME, '');
  1361.  
  1362.     if EnglishName = '' then
  1363.       EnglishName := TIvDictionary.ComposeLanguageName(
  1364.         GetLocaleStr(Locale, LOCALE_SENGLANGUAGE, ''),
  1365.         primary,
  1366.         codePage,
  1367.         False,
  1368.         nil);
  1369.  
  1370.     if NativeName = '' then
  1371.       NativeName := GetLocaleStr(Locale, LOCALE_SNATIVELANGNAME, '');
  1372.  
  1373.     if FCodePage = 0 then
  1374.       FCodePage := IvLangIdToCodePage(Locale);
  1375. {$ENDIF}
  1376.     if FCodePage = 0 then
  1377.       FCodePage := WESTERN_CP_C;
  1378.   end;
  1379.  
  1380.   if FActiveSub = 0 then
  1381.     FActiveSub := FDefaultSub;
  1382.     
  1383. {$IFDEF WIN32}
  1384.   if FCharset = 0 then
  1385.     FCharset := IvCodePageToCharset(FCodePage);
  1386. {$ENDIF}
  1387. end;
  1388.  
  1389. procedure TIvLanguage.Assign(source: TIvLanguage);
  1390. begin
  1391.   FCodePage := source.FCodePage;
  1392. {$IFDEF WIN32}
  1393.   FCharset := source.FCharset;
  1394. {$ENDIF}
  1395.   FPrimary := source.FPrimary;
  1396.   FVariant := source.FVariant;
  1397.   FDefaultSub := source.FDefaultSub;
  1398.   FActiveSub := source.FActiveSub;
  1399.   FSubs.Assign(source.FSubs);
  1400.   FISOLanguage := source.FISOLanguage;
  1401.   FISODefaultCountry := source.FISODefaultCountry;
  1402.   FISOCountries.Assign(source.FISOCountries);
  1403.   FEnglishName := source.FEnglishName;
  1404.   FNativeName := source.FNativeName;
  1405.   FFontName := source.FFontName;
  1406.   FFontSize := source.FFontSize;
  1407.   FOptions := source.FOptions;
  1408. end;
  1409.  
  1410. function TIvLanguage.Copy: TIvLanguage;
  1411. begin
  1412.   Result := TIvLanguage.Create;
  1413.   Result.Assign(Self);
  1414. end;
  1415.  
  1416. function TIvLanguage.GetOptionsAsInt: Integer;
  1417. begin
  1418.   Result := 0;
  1419.  
  1420.   if ivloTest in FOptions then
  1421.     Result := Result or TEST_MASK_C;
  1422.  
  1423.   if ivloPureASCII in FOptions then
  1424.     Result := Result or PURE_ASCII_MASK_C;
  1425. end;
  1426.  
  1427. procedure TIvLanguage.SetOptionsAsInt(value: Integer);
  1428. begin
  1429.   FOptions := [];
  1430.  
  1431.   if (TEST_MASK_C and value) <> 0 then
  1432.     FOptions := FOptions + [ivloTest];
  1433.  
  1434.   if (PURE_ASCII_MASK_C and value) <> 0 then
  1435.     FOptions := FOptions + [ivloPureASCII];
  1436. end;
  1437.  
  1438. function TIvLanguage.GetCharsetType: TIvCharacterSetType;
  1439. begin
  1440.   Result := IvGetCharacterSetType(Locale);
  1441. end;
  1442.  
  1443. function TIvLanguage.GetAllSubs: String;
  1444. var
  1445.   i: Integer;
  1446. begin
  1447.   Result := '';
  1448.   for i := 0 to FSubs.Count - 1 do
  1449.   begin
  1450.     if i = 0 then
  1451.       Result := FSubs[i]
  1452.     else
  1453.       Result := Result + IV_SUB_SEPARATOR_C + FSubs[i];
  1454.   end;
  1455. end;
  1456.  
  1457. procedure TIvLanguage.SetAllSubs(const value: String);
  1458. var
  1459.   sub: Integer;
  1460.   parser: TIvStringParser;
  1461. begin
  1462.   FSubs.Clear;
  1463.   parser := TIvStringParser.CreateValue(value, IV_SUB_SEPARATOR_C);
  1464.   while not parser.Eol do
  1465.   begin
  1466.     sub := parser.GetInteger;
  1467.     if sub > 0 then
  1468.       FSubs.Add(IntToStr(sub));
  1469.   end;
  1470.   parser.Free;
  1471. end;
  1472.  
  1473. function TIvLanguage.GetBundleExtension: String;
  1474. begin
  1475.   if FISOCountries.Count > 0 then
  1476.     Result := '_' + ISOLanguage + '_' + FISOCountries[0]
  1477.   else
  1478.     Result := '_' + ISOLanguage;
  1479. end;
  1480.  
  1481. function TIvLanguage.GetISOAllCountries: String;
  1482. var
  1483.   i: Integer;
  1484. begin
  1485.   Result := '';
  1486.   for i := 0 to FISOCountries.Count - 1 do
  1487.   begin
  1488.     if i = 0 then
  1489.       Result := FISOCountries[i]
  1490.     else
  1491.       Result := Result + IV_SUB_SEPARATOR_C + FISOCountries[i];
  1492.   end;
  1493. end;
  1494.  
  1495. procedure TIvLanguage.SetISOAllCountries(const value: String);
  1496. var
  1497.   parser: TIvStringParser;
  1498. begin
  1499.   FISOCountries.Clear;
  1500.   parser := TIvStringParser.CreateValue(value, IV_SUB_SEPARATOR_C);
  1501.   while not parser.Eol do
  1502.     FISOCountries.Add(parser.GetString);
  1503.   parser.Free;
  1504. end;
  1505.  
  1506. class function TIvLanguage.SubStrToSubId(const str: String): Integer;
  1507. var
  1508.   parser: TIvAnsiParser;
  1509. {$IFNDEF WIN32}
  1510.   buffer: array[0..255] of Char;
  1511. {$ENDIF}
  1512. begin
  1513.   if str = '' then
  1514.     Result := 0
  1515.   else
  1516.   begin
  1517.     parser := TIvAnsiParser.CreateValue(
  1518. {$IFDEF WIN32}
  1519.       str,
  1520. {$ELSE}
  1521.       StrPCopy(buffer, str),
  1522. {$ENDIF}
  1523.       ',');
  1524.     try
  1525.       Result := parser.GetInteger;
  1526.     finally
  1527.       parser.Free;
  1528.     end;
  1529.   end;
  1530. end;
  1531.  
  1532. function TIvLanguage.GetSub: Integer;
  1533. begin
  1534.   if SubCount = 0 then
  1535.     Result := SUBLANG_NEUTRAL
  1536.   else
  1537.     Result := Subs[0];
  1538. end;
  1539.  
  1540. function TIvLanguage.GetSubCount: Integer;
  1541. begin
  1542.   Result := FSubs.Count;
  1543. end;
  1544.  
  1545. procedure TIvLanguage.ClearSubs;
  1546. begin
  1547.   FSubs.Clear;
  1548. end;
  1549.  
  1550. procedure TIvLanguage.AddSub(sub: Integer);
  1551. var
  1552.   i: Integer;
  1553.   found: Boolean;
  1554. begin
  1555.   found := False;
  1556.   for i := 0 to SubCount - 1 do
  1557.     if Subs[i] = sub then
  1558.     begin
  1559.       found := True;
  1560.       Break;
  1561.     end;
  1562.  
  1563.   if not found then
  1564.     FSubs.Add(IntToStr(sub));
  1565. end;
  1566.  
  1567. function TIvLanguage.GetSubs(i: Integer): Integer;
  1568. begin
  1569.   Result := StrToInt(FSubs[i]);
  1570. end;
  1571.  
  1572. procedure TIvLanguage.SetActiveSub(value: Integer);
  1573. var
  1574.   i: Integer;
  1575.   found: Boolean;
  1576. begin
  1577.   if value <> FActiveSub then
  1578.   begin
  1579.     found := False;
  1580.     for i := 0 to SubCount - 1 do
  1581.       if value = Subs[i] then
  1582.       begin
  1583.         found := True;
  1584.         Break;
  1585.       end;
  1586.       
  1587.     if (not found and (SubCount > 0)) or (value < 0) then
  1588.       FActiveSub := FDefaultSub
  1589.     else
  1590.       FActiveSub := value
  1591.   end;
  1592. end;
  1593.  
  1594. function TIvLanguage.GetISOCountry: String;
  1595. begin
  1596.   if ISOCountryCount = 0 then
  1597.     Result := ''
  1598.   else
  1599.     Result := ISOCountries[0];
  1600. end;
  1601.  
  1602. function TIvLanguage.GetISOCountryCount: Integer;
  1603. begin
  1604.   Result := FISOCOuntries.Count;
  1605. end;
  1606.  
  1607. function TIvLanguage.GetISOCountries(i: Integer): String;
  1608. begin
  1609.   Result := FISOCOuntries[i];
  1610. end;
  1611.  
  1612. procedure TIvLanguage.ClearISOCountries;
  1613. begin
  1614.   FISOCOuntries.Clear;
  1615. end;
  1616.  
  1617. procedure TIvLanguage.AddISOCountry(country: String);
  1618. var
  1619.   i: Integer;
  1620.   found: Boolean;
  1621. begin
  1622.   found := False;
  1623.   for i := 0 to ISOCountryCount - 1 do
  1624.     if ISOCountries[i] = country then
  1625.     begin
  1626.       found := True;
  1627.       Break;
  1628.     end;
  1629.  
  1630.   if not found then
  1631.     FISOCOuntries.Add(country);
  1632. end;
  1633.  
  1634. function TIvLanguage.GetDefaultLocale: Integer;
  1635. begin
  1636.   { The fake language contains the primary id in the default sub id }
  1637.  
  1638.   if FPrimary = LANG_NEUTRAL then
  1639.     Result := IvMakeLcId(IvMakeLangId(FDefaultSub, SUBLANG_NEUTRAL), SORT_DEFAULT)
  1640.   else
  1641.     Result := IvMakeLcId(IvMakeLangId(FPrimary, FDefaultSub), SORT_DEFAULT);
  1642. end;
  1643.  
  1644. function TIvLanguage.GetActiveLocale: Integer;
  1645. begin
  1646.   Result := IvMakeLcId(IvMakeLangId(FPrimary, FActiveSub), SORT_DEFAULT);
  1647. end;
  1648.  
  1649. function TIvLanguage.GetLangId: Integer;
  1650. begin
  1651.   if FPrimary = LANG_NEUTRAL then
  1652.     Result := IvMakeLangId(LANG_NEUTRAL, SUBLANG_NEUTRAL)
  1653.   else if FSubs.Count = 0 then
  1654.     Result := IvMakeLangId(FPrimary, SUBLANG_NEUTRAL)
  1655.   else
  1656.     Result := IvMakeLangId(FPrimary, Subs[0]);
  1657. end;
  1658.  
  1659. function TIvLanguage.GetLocale: Integer;
  1660. var
  1661.   sub: Integer;
  1662. begin
  1663.   if FPrimary = LANG_NEUTRAL then
  1664.     Result := IvMakeLcId(IvMakeLangId(LANG_NEUTRAL, SUBLANG_NEUTRAL), SORT_DEFAULT)
  1665.   else
  1666.   begin
  1667.     if FSubs.Count > 0 then
  1668.       sub := Subs[0]
  1669.     else
  1670.       sub := FDefaultSub;
  1671.  
  1672.     { If sub is not specified, determines the sub from the code page }
  1673.  
  1674.     if sub = 0 then
  1675.     begin
  1676. {$IFDEF IVPRO}
  1677.       if FPrimary = LANG_CHINESE then
  1678.         case FCodePage of
  1679.           SIMPLIFIED_CHINESE_CP_C: sub := SUBLANG_CHINESE_SIMPLIFIED;
  1680.           TRADITIONAL_CHINESE_CP_C: sub := SUBLANG_CHINESE_TRADITIONAL;
  1681.         end;
  1682. {$ENDIF}
  1683.       if FPrimary = LANG_CROATIAN then
  1684.         case FCodePage of
  1685.           EAST_EUROPE_CP_C: sub := SUBLANG_DEFAULT;
  1686.           CYRILLIC_CP_C: sub := SUBLANG_SERBIAN_CYRILLIC;
  1687.         end;
  1688.     end;
  1689.  
  1690.     Result := IvMakeLcId(IvMakeLangId(FPrimary, sub), SORT_DEFAULT);
  1691.   end;
  1692. end;
  1693.  
  1694. function TIvLanguage.GetDisplayName(
  1695.   displayName: TIvDisplayName;
  1696.   dictionary: TIvDictionary): String;
  1697. begin
  1698.   case displayName of
  1699.     ivdnEnglish:
  1700.       Result := TIvDictionary.ComposeLanguageName(
  1701.         EnglishName,
  1702.         Primary,
  1703.         CodePage,
  1704.         False,
  1705.         nil);
  1706.  
  1707.     ivdnNative:
  1708.       Result := TIvDictionary.ComposeLanguageName(
  1709.         NativeName,
  1710.         Primary,
  1711.         CodePage,
  1712.         False,
  1713.         nil);
  1714.  
  1715.     ivdnTranslated:
  1716.       Result := TIvDictionary.ComposeLanguageName(
  1717.         EnglishName,
  1718.         Primary,
  1719.         CodePage,
  1720.         True,
  1721.         dictionary);
  1722.   end;
  1723. end;
  1724.  
  1725.  
  1726. { TIvLocale }
  1727.  
  1728. function TIvLocale.GetLangId: Integer;
  1729. begin
  1730.   Result := IvMakeLangId(Primary, Sub);
  1731. end;
  1732.  
  1733. procedure TIvLocale.SetLangId(value: Integer);
  1734. begin
  1735.   Primary := IvGetPrimaryFromLocale(value);
  1736.   Sub := IvGetPrimaryFromLocale(value);
  1737. end;
  1738.  
  1739. function TIvLocale.GetLocale: Integer;
  1740. begin
  1741.   Result := IvMakeLcId(IvMakeLangId(Primary, Sub), SortId);
  1742. end;
  1743.  
  1744. procedure TIvLocale.SetLocale(value: Integer);
  1745. begin
  1746.   Primary := IvGetPrimaryFromLocale(value);
  1747.   Sub := IvGetPrimaryFromLocale(value);
  1748. end;
  1749.  
  1750. function TIvLocale.GetCharsetType: TIvCharacterSetType;
  1751. begin
  1752.   Result := IvGetCharacterSetType(Locale);
  1753. end;
  1754.  
  1755. function TIvLocale.GetEMU: TIvEMU;
  1756. begin
  1757.   if IsEMUMember(Locale) then
  1758.     Result := GetEMUPhase
  1759.   else
  1760.     Result := iveNone;
  1761. end;
  1762.  
  1763. function TIvLocale.GetEMUCurrencyString: String;
  1764. begin
  1765.   if euroUsage = iveIgnore then
  1766.     Result := CurrencyString
  1767.   else
  1768.     case EMU of
  1769.       iveLocalAndEuro:
  1770.         if euroUsage = iveNormal then
  1771.           Result := CurrencyString
  1772.         else
  1773.           Result := EURO_CHAR_C;
  1774.  
  1775.       iveEuroAndLocal,
  1776.       iveEuro:
  1777.         Result := EURO_CHAR_C;
  1778.     else
  1779.       Result := CurrencyString;
  1780.     end;
  1781. end;
  1782.  
  1783. function TIvLocale.Copy: TIvLocale;
  1784. begin
  1785.   Result := TIvLocale.Create;
  1786.   Result.Assign(Self);
  1787. end;
  1788.  
  1789. procedure TIvLocale.Assign(source: TIvLocale);
  1790. var
  1791.   i: Integer;
  1792. begin
  1793.   Primary := source.Primary;
  1794.   Sub := source.Sub;
  1795.   CodePage := source.CodePage;
  1796.   ISOLanguage := source.ISOLanguage;
  1797.   ISOCountry := source.ISOCountry;
  1798.   IsCustom := source.IsCustom;
  1799.  
  1800.   EnglishLanguageName := source.EnglishLanguageName;
  1801.   EnglishCountryName := source.EnglishCountryName;
  1802.   NativeLanguageName := source.NativeLanguageName;
  1803.   NativeCountryName := source.NativeCountryName;
  1804.   Win16LanguageName := source.Win16LanguageName;
  1805.   Win16CountryName := source.Win16CountryName;
  1806.  
  1807.   CurrencyString := source.CurrencyString;
  1808.   CurrencyFormat := source.CurrencyFormat;
  1809.   NegCurrFormat := source.NegCurrFormat;
  1810.   CurrencyDecimals := source.CurrencyDecimals;
  1811.   ThousandSeparator := source.ThousandSeparator;
  1812.   DecimalSeparator := source.DecimalSeparator;
  1813.  
  1814.   DateSeparator := source.DateSeparator;
  1815.   ShortDateFormat := source.ShortDateFormat;
  1816.   LongDateFormat := source.LongDateFormat;
  1817.  
  1818.   TimeSeparator := source.TimeSeparator;
  1819.   TimeAMString := source.TimeAMString;
  1820.   TimePMString := source.TimePMString;
  1821.   TimeLeadingZeros := source.TimeLeadingZeros;
  1822.   TimeFormat := source.TimeFormat;
  1823.   TimeMarkPosition := source.TimeMarkPosition;
  1824.  
  1825.   MeasurementSystem := source.MeasurementSystem;
  1826.   CalendarType := source.CalendarType;
  1827.   OptionalCalendarType := source.OptionalCalendarType;
  1828.   FirstDayOfWeek := source.FirstDayOfWeek;
  1829.   FirstWeekOfYear := source.FirstWeekOfYear;
  1830.  
  1831.   for i := 1 to 12 do
  1832.   begin
  1833.     ShortMonthNames[i] := source.ShortMonthNames[i];
  1834.     LongMonthNames[i] := source.LongMonthNames[i];
  1835.   end;
  1836.   for i := 1 to 7 do
  1837.   begin
  1838.     ShortDayNames[i] := source.ShortDayNames[i];
  1839.     LongDayNames[i] := source.LongDayNames[i];
  1840.   end;
  1841. end;
  1842.  
  1843. function TIvLocale.GetDisplayName(
  1844.   displayName: TIvDisplayName;
  1845.   dictionary: TIvDictionary): String;
  1846. begin
  1847.   case displayName of
  1848.     ivdnEnglish:
  1849.       Result := TIvDictionary.ComposeLocaleName(
  1850.         EnglishLanguageName,
  1851.         EnglishCountryName,
  1852.         Primary,
  1853.         Sub,
  1854.         CodePage,
  1855.         False,
  1856.         nil);
  1857.  
  1858.     ivdnNative:
  1859.       Result := TIvDictionary.ComposeLocaleName(
  1860.         NativeLanguageName,
  1861.         NativeCountryName,
  1862.         Primary,
  1863.         Sub,
  1864.         CodePage,
  1865.         False,
  1866.         nil);
  1867.  
  1868.     ivdnTranslated:
  1869.       Result := TIvDictionary.ComposeLocaleName(
  1870.         EnglishLanguageName,
  1871.         EnglishCountryName,
  1872.         Primary,
  1873.         Sub,
  1874.         CodePage,
  1875.         True,
  1876.         dictionary);
  1877.   end;
  1878. end;
  1879.  
  1880. procedure TIvLocale.Init;
  1881. begin
  1882.   if Primary <> LANG_NEUTRAL then
  1883.   begin
  1884. {$IFDEF WIN32}
  1885.     if EnglishLanguageName = '' then
  1886.       EnglishLanguageName := GetLocaleStr(Locale, LOCALE_SENGLANGUAGE, '');
  1887.  
  1888.     if NativeLanguageName = '' then
  1889.       NativeLanguageName := GetLocaleStr(Locale, LOCALE_SNATIVELANGNAME, '');
  1890.  
  1891.     if EnglishCountryName = '' then
  1892.       EnglishCountryName := GetLocaleStr(Locale, LOCALE_SENGCOUNTRY, '');
  1893.  
  1894.     if NativeCountryName = '' then
  1895.       NativeCountryName := GetLocaleStr(Locale, LOCALE_SNATIVECTRYNAME, '');
  1896.  
  1897.     if CodePage = 0 then
  1898.       CodePage := IvLangIdToCodePage(Locale);
  1899. {$ENDIF}
  1900.     if CodePage = 0 then
  1901.       CodePage := 1252;
  1902.   end;
  1903.  
  1904. {$IFDEF WIN32}
  1905.   if Charset = 0 then
  1906.     Charset := IvLangIdToCharset(Locale);
  1907. {$ENDIF}
  1908. end;
  1909.  
  1910.  
  1911. { TIvContext }
  1912.  
  1913. constructor TIvContext.CreateValue(const form, component: String);
  1914. begin
  1915.   inherited Create;
  1916.   FForm := form;
  1917.   FComponent := component;
  1918. end;
  1919.  
  1920. procedure TIvContext.Clear;
  1921. begin
  1922.   FForm := '';
  1923.   FComponent := '';
  1924. end;
  1925.  
  1926. procedure TIvContext.Assign(context: TIvContext);
  1927. begin
  1928.   FForm := context.Form;
  1929.   FComponent := context.Component;
  1930. end;
  1931.  
  1932. function TIvContext.Equals(context: TIvContext): Boolean;
  1933. begin
  1934.   Result := (FForm = context.Form) and (FComponent = context.Component);
  1935. end;
  1936.  
  1937. class function TIvContext.ContextCodeToType(value: TIvContextCode): TIvContextType;
  1938. begin
  1939.   case value of
  1940.     ivccFlat: Result := [];
  1941.     ivccFull: Result := [ivctForm, ivctComponent];
  1942.     ivccComponent: Result := [ivctComponent];
  1943.     ivccForm: Result := [ivctForm];
  1944.   end;
  1945. end;
  1946.  
  1947. class function TIvContext.ContextTypeToCode(value: TIvContextType): TIvContextCode;
  1948. begin
  1949.   if value = [] then
  1950.     Result := ivccFlat
  1951.   else if value = [ivctForm, ivctComponent] then
  1952.     Result := ivccFull
  1953.   else if value = [ivctComponent] then
  1954.     Result := ivccComponent
  1955.   else
  1956.     Result := ivccForm;
  1957. end;
  1958.  
  1959.  
  1960. { TIvTranslation }
  1961.  
  1962. constructor TIvTranslation.CreateValue(const str, form, component: String);
  1963. begin
  1964.   inherited Create;
  1965.   Self.Str := str;
  1966.   Self.Form := form;
  1967.   Self.Component := component;
  1968. end;
  1969.  
  1970. function TIvTranslation.GetKey: String;
  1971. begin
  1972.   Result := ComposeKey(Str, Form, Component);
  1973. end;
  1974.  
  1975. class function TIvTranslation.ComposeKey(const str, form, component: String): String;
  1976. begin
  1977.   Result := Str + CONTEXT_SEPARATOR_C + Form + Component;
  1978. end;
  1979.  
  1980.  
  1981. { TIvDictionary }
  1982.  
  1983. constructor TIvDictionary.Create(owner: TComponent);
  1984. begin
  1985.   inherited Create(owner);
  1986.  
  1987.   Dictionaries.Add(Self);
  1988. {$IFDEF IVWIDE}
  1989.   if not Assigned(Application.OnException) then
  1990.     Application.OnException := HandleException;
  1991. {$ENDIF}
  1992.  
  1993.   FOpen := False;
  1994.   FContextType := [];
  1995.   FActiveLocale := 0;
  1996.   FNativeLocale := 0;
  1997.   FLocale := IvMakeLcId(IvMakeLangId(LANG_NEUTRAL, SUBLANG_DEFAULT), SORT_DEFAULT);
  1998.   FLanguage := LANG_USER;
  1999.   FBinding := ivbiLocaleToLanguage;
  2000.   FEuro := iveNormal;
  2001.   FDictionaryCode := Integer(liProfessional);
  2002.  
  2003.   FOptions := [ivdoUpdateLocaleVariables, ivdoAutoTranslate, ivdoYear2000, ivdoTranslateResourceStrings];
  2004.   FMissingTranslation := ivmtUseNative;
  2005. {$IFDEF WIN32}
  2006.   FCheckLevel := ivclCodePage;
  2007. {$ENDIF}
  2008.  
  2009.   FTranslators := TList.Create;
  2010.   FLanguageData := TIvLanguage.Create;
  2011.   FTempLanguageData := nil;
  2012.   FLocaleData := TIvLocale.Create;
  2013.   FTempLocaleData := nil;
  2014. end;
  2015.  
  2016. destructor TIvDictionary.Destroy;
  2017. begin
  2018.   UnbindTranslators;
  2019.   if Dictionaries <> nil then
  2020.     Dictionaries.Remove(Self);
  2021.   FLocaleData.Free;
  2022.   FTempLocaleData.Free;
  2023.   FLanguageData.Free;
  2024.   FTempLanguageData.Free;
  2025.   FTranslators.Free;
  2026.   inherited Destroy;
  2027. end;
  2028.  
  2029. function TIvDictionary.GetContextCode: TIvContextCode;
  2030. begin
  2031.   Result := TIvContext.ContextTypeToCode(FContextType);
  2032. end;
  2033.  
  2034. procedure TIvDictionary.SetDictionaryName(const value: String);
  2035. begin
  2036.   FDictionaryName := value;
  2037. end;
  2038.  
  2039. function TIvDictionary.GetPrimaryLanguage: Integer;
  2040. begin
  2041.   Result := IvGetPrimaryFromLocale(FLocale);
  2042. end;
  2043.  
  2044. procedure TIvDictionary.SetPrimaryLanguage(value: Integer);
  2045. begin
  2046.   SetLocale(IvMakeLcId(IvMakeLangId(value, SubLanguage), SORT_DEFAULT));
  2047. end;
  2048.  
  2049. function TIvDictionary.GetSubLanguage: Integer;
  2050. begin
  2051.   Result := IvGetSubFromLocale(FLocale);
  2052. end;
  2053.  
  2054. procedure TIvDictionary.SetSubLanguage(value: Integer);
  2055. begin
  2056.   SetLocale(IvMakeLcId(IvMakeLangId(PrimaryLanguage, value), SORT_DEFAULT));
  2057. end;
  2058.  
  2059. procedure TIvDictionary.ReadDictionaryCode(reader: TReader);
  2060. {$IFDEF IVBINARY}
  2061. var
  2062.   valid: Boolean;
  2063.   dialog: TIvDemoDialog;
  2064. {$ENDIF}
  2065. begin
  2066.   FDictionaryCode := reader.ReadInteger;
  2067. {$IFDEF IVBINARY}
  2068.   if ((FDictionaryCode = Integer(liNone)) or
  2069.     (FDictionaryCode = Integer(liEvaluation))) and
  2070.     not IsDesignTime then
  2071.   begin
  2072.   {$IFDEF WIN32}
  2073.     valid := GetTimeStampDaysLeft(
  2074.       KEY_C,
  2075.       STAMP_C,
  2076.     {$IFDEF IVVB}
  2077.       VB_CRYPTO_KEY_C
  2078.     {$ELSE}
  2079.       VCL_CRYPTO_KEY_C
  2080.     {$ENDIF}
  2081.       ) > 0;
  2082.   {$ELSE}
  2083.     valid := GetTimeStampDaysLeft(
  2084.       INI_FILE_C,
  2085.       SECTION_C,
  2086.       STAMP_C,
  2087.     {$IFDEF IVVB}
  2088.       VB_CRYPTO_KEY_C
  2089.     {$ELSE}
  2090.       VCL_CRYPTO_KEY_C
  2091.     {$ENDIF}
  2092.       ) > 0;
  2093.   {$ENDIF}
  2094.  
  2095.     if not valid then
  2096.     begin
  2097.       dialog := TIvDemoDialog.CreateValue(nil, KEY_C);
  2098.       try
  2099.         dialog.ShowModal;
  2100.       finally
  2101.         dialog.Free;
  2102.       end;
  2103.     end;
  2104.   end;
  2105. {$ENDIF}
  2106. end;
  2107.  
  2108. procedure TIvDictionary.WriteDictionaryCode(writer: TWriter);
  2109. {$IFDEF IVBINARY}
  2110. var
  2111.   str: String;
  2112.   code: Integer;
  2113. {$ENDIF}
  2114. begin
  2115. {$IFDEF IVBINARY}
  2116.   try
  2117.     str := GetMLRegistryValue(DICTIONARY_CODE_C, '');
  2118.     code := StrToInt(str);
  2119.     if (code < Integer(Low(TIvLicense))) or (code > Integer(High(TIvLicense))) then
  2120.       raise Exception.Create('');
  2121.   except
  2122.     MessageDlg(
  2123.       'The Multilizer configuration is corrupted.'#13#10 +
  2124.       'Install Multilizer again!',
  2125.       mtInformation,
  2126.       [mbOK],
  2127.       0);
  2128.     code := Integer(liEvaluation);
  2129.   end;
  2130.   writer.WriteInteger(code);
  2131. {$ENDIF}
  2132. end;
  2133.  
  2134. procedure TIvDictionary.DefineProperties(filer: TFiler);
  2135. begin
  2136.   inherited DefineProperties(filer);
  2137.   filer.DefineProperty(
  2138.     'DictionaryCode',
  2139.     ReadDictionaryCode,
  2140.     WriteDictionaryCode,
  2141. {$IFDEF IVBINARY}
  2142.     True
  2143. {$ELSE}
  2144.     False
  2145. {$ENDIF}
  2146.     );
  2147. end;
  2148.  
  2149. class procedure TIvDictionary.SetTimeFormats(
  2150.   format: TIvTimeFormat;
  2151.   markPosition: TIvTimeMarkPosition;
  2152.   leadingZeros: Boolean;
  2153.   var shortTimeFormat, longTimeFormat: String);
  2154. var
  2155.   hourFormat, timePrefix, timePostfix: String;
  2156. begin
  2157.   if leadingZeros then
  2158.     hourFormat := 'hh'
  2159.   else
  2160.     hourFormat := 'h';
  2161.  
  2162.   timePostfix := '';
  2163.   timePrefix := '';
  2164.   if format = ivtf12 then
  2165.   begin
  2166.     case markPosition of
  2167.       ivtmSuffix: timePostfix := ' AMPM';
  2168.       ivtmPrefix: timePrefix := 'AMPM ';
  2169.     end;
  2170.   end;
  2171.  
  2172.   shortTimeFormat := timePrefix + hourFormat + ':mm' + timePostfix;
  2173.   longTimeFormat := timePrefix + hourFormat + ':mm:ss' + timePostfix;
  2174. end;
  2175.  
  2176. class function TIvDictionary.TranslateDateFormat(const formatStr: String): String;
  2177. var
  2178.   i: Integer;
  2179. {$IFDEF IVIME}
  2180.   CalType: Integer;
  2181.   Era, RemoveEra: Boolean;
  2182. {$ENDIF}
  2183. begin
  2184. {$IFDEF IVIME}
  2185.   I := 1;
  2186.   Result := '';
  2187.   CalType := StrToIntDef(GetLocaleStr(GetThreadLocale, LOCALE_ICALENDARTYPE, '1'), 1);
  2188.   Era := CalType in [CAL_JAPAN, CAL_TAIWAN, CAL_KOREA];
  2189.   if not Era then
  2190.   begin
  2191.     RemoveEra := SysLocale.PriLangID in [LANG_JAPANESE, LANG_CHINESE, LANG_KOREAN];
  2192.     if RemoveEra then
  2193.     begin
  2194.       While I <= Length(FormatStr) do
  2195.       begin
  2196.         if not (FormatStr[I] in ['g', 'G']) then
  2197.           Result := Result + FormatStr[I];
  2198.         Inc(I);
  2199.       end;
  2200.     end
  2201.     else
  2202.       Result := FormatStr;
  2203.     Exit;
  2204.   end;
  2205.  
  2206.   while I <= Length(FormatStr) do
  2207.   begin
  2208.     if FormatStr[I] in LeadBytes then
  2209.     begin
  2210.       Result := Result + Copy(FormatStr, I, 2);
  2211.       Inc(I, 2);
  2212.     end else
  2213.     begin
  2214.       if StrLIComp(@FormatStr[I], 'gg', 2) = 0 then
  2215.       begin
  2216.         Result := Result + 'ggg';
  2217.         Inc(I, 1);
  2218.       end
  2219.       else if StrLIComp(@FormatStr[I], 'yyyy', 4) = 0 then
  2220.       begin
  2221.         Result := Result + 'ee';
  2222.         Inc(I, 4-1);
  2223.       end
  2224.       else if StrLIComp(@FormatStr[I], 'yy', 2) = 0 then
  2225.       begin
  2226.         Result := Result + 'ee';
  2227.         Inc(I, 2-1);
  2228.       end
  2229.       else if FormatStr[I] in ['y', 'Y'] then
  2230.         Result := Result + 'e'
  2231.       else
  2232.         Result := Result + FormatStr[I];
  2233.       Inc(I);
  2234.     end;
  2235.   end;
  2236. {$ELSE}
  2237.   Result := formatStr;
  2238.   for i := 1 to Length(Result) do
  2239.     if Result[i] = '''' then
  2240.       Result[i] := '"';
  2241. {$ENDIF}
  2242. end;
  2243.  
  2244. procedure TIvDictionary.SynchronizeLocale;
  2245. var
  2246.   oldLocale: Integer;
  2247. begin
  2248.   { Sets the locale match the active language }
  2249.  
  2250.   if IsOpen then
  2251.   begin
  2252.     oldLocale := FActiveLocale;
  2253.     InitLocale(FLanguageData.DefaultLocale);
  2254.     if FActiveLocale <> oldLocale then
  2255.       LanguageChanged(False, True);
  2256.   end;
  2257. end;
  2258.  
  2259. procedure TIvDictionary.SynchronizeLanguage;
  2260. var
  2261.   oldLanguage: Integer;
  2262. begin
  2263.   { Sets the language match the active locale }
  2264.  
  2265.   if IsOpen then
  2266.   begin
  2267.     oldLanguage := FActiveLanguage;
  2268.     InitLanguage(LocaleToLanguage(FActiveLocale));
  2269.     if FActiveLanguage <> oldLanguage then
  2270.       LanguageChanged(True, False);
  2271.   end;
  2272. end;
  2273.  
  2274. procedure TIvDictionary.SetLanguage(value: Integer);
  2275. var
  2276.   oldLocale: Integer;
  2277. begin
  2278.   if not IsOpen then
  2279.     FLanguage := value
  2280.   else if (value < LANG_SYSTEM) or (value >= LanguageCount) then
  2281.     raise ERangeError.Create('Language index ' + IntToStr(value) + ' is out of range')
  2282.   else if value <> FLanguage then
  2283.   begin
  2284.     FLanguage := value;
  2285.  
  2286.     { Checks the language and accepts it }
  2287.  
  2288.     InitLanguage(FLanguage);
  2289.  
  2290.     { Updates the locale if the language and locale has been bound together }
  2291.  
  2292.     oldLocale := FActiveLocale;
  2293.  
  2294.     if FBinding = ivbiLocaleToLanguage then
  2295.       InitLocale(FLanguageData.ActiveLocale);
  2296.  
  2297.     { Updates the language }
  2298.  
  2299.     LanguageChanged(True, oldLocale <> FActiveLocale);
  2300.   end;
  2301. end;
  2302.  
  2303. procedure TIvDictionary.SetLocale(value: Integer);
  2304. var
  2305.   oldLanguage, newLanguage: Integer;
  2306. begin
  2307.   if not IsOpen then
  2308.     FLocale := value
  2309.   else if value <> FLocale then
  2310.   begin
  2311.     FLocale := value;
  2312.  
  2313.     { Checks the locale and accepts it }
  2314.  
  2315.     InitLocale(FLocale);
  2316.  
  2317.     { Updates the language if the language and locale has been bound together }
  2318.  
  2319.     oldLanguage := FActiveLanguage;
  2320.  
  2321.     if FBinding = ivbiLanguageToLocale then
  2322.     begin
  2323.       newLanguage := LocaleToLanguage(FActiveLocale);
  2324.       if newLanguage < 0 then
  2325.         InitLanguage(DefaultLanguage)
  2326.       else
  2327.       begin
  2328.         { Inits the language. However the default initialization sets the language
  2329.           locale to the default locale of the language. However, in this case
  2330.           the active locale is used. }
  2331.  
  2332.         InitLanguage(newLanguage);
  2333.         FLanguageLocale := FActiveLocale;
  2334.       end;
  2335.     end;
  2336.  
  2337.     LanguageChanged(oldLanguage <> FActiveLanguage, True);
  2338.   end;
  2339. end;
  2340.  
  2341. {
  2342. procedure TIvDictionary.InitLocale(locale: Integer);
  2343.  
  2344.  
  2345. begin
  2346.   if FBinding = ivbiLocaleToLanguage then
  2347.   begin
  2348.     if FOriginalLanguage = LANG_SYSTEM then
  2349.       locale := CheckLocale(GetSystemDefaultLCID, locale)
  2350.     else
  2351.       locale := CheckLocale(GetUserDefaultLCID, locale);
  2352.   end;
  2353. end;
  2354. }
  2355.  
  2356. procedure TIvDictionary.InitLanguage(language: Integer);
  2357. var
  2358.   primary, sub: Integer;
  2359.  
  2360.   function CheckLocale(systemLocale, defaultLocale: Integer): Integer;
  2361.   begin
  2362.     if IvGetPrimaryFromLocale(systemLocale) = IvGetPrimaryFromLocale(defaultLocale) then
  2363.       Result := systemLocale
  2364.     else
  2365.       Result := defaultLocale;
  2366.   end;
  2367.  
  2368. begin
  2369.   { Inits the language, the language data and the language locale }
  2370.  
  2371.   case language of
  2372.     LANG_SYSTEM: FActiveLanguage := LocaleToLanguage(GetSystemDefaultLCID);
  2373.     LANG_USER: FActiveLanguage := LocaleToLanguage(GetUserDefaultLCID);
  2374.   else
  2375.     FActiveLanguage := language;
  2376.   end;
  2377.  
  2378.   if FActiveLanguage < 0 then
  2379.     FActiveLanguage := DefaultLanguage;
  2380.   if FActiveLanguage = -1 then
  2381.     raise EIvMulti.Create('System does not support any language of the dicitonary!');
  2382.  
  2383.   FLanguageData.Free;
  2384.   FLanguageData := TIvLanguage.Create;
  2385.   if LanguageCount > 0 then
  2386.   begin
  2387.     { Gets first the language data of the native language }
  2388.  
  2389.     GetLanguageData(0, FLanguageData);
  2390.     sub := SUBLANG_NEUTRAL;
  2391.     case FLanguageData.CodePage of
  2392.       JAPANESE_CP_C: primary := LANG_JAPANESE;
  2393.  
  2394.       KOREAN_CP_C:
  2395.       begin
  2396.         primary := LANG_KOREAN;
  2397.         sub := SUBLANG_KOREAN;
  2398.       end;
  2399.  
  2400.       KOREAN_JOHAB_CP_C:
  2401.       begin
  2402.         primary := LANG_KOREAN;
  2403.         sub := SUBLANG_KOREAN_JOHAB;
  2404.       end;
  2405.  
  2406.       SIMPLIFIED_CHINESE_CP_C:
  2407.       begin
  2408.         primary := LANG_CHINESE;
  2409.         sub := SUBLANG_CHINESE_SIMPLIFIED;
  2410.       end;
  2411.  
  2412.       TRADITIONAL_CHINESE_CP_C:
  2413.       begin
  2414.         primary := LANG_CHINESE;
  2415.         sub := SUBLANG_CHINESE_TRADITIONAL;
  2416.       end;
  2417.     else
  2418.       primary := LANG_ENGLISH;
  2419.     end;
  2420.     FNativeLocale := IvMakeLangId(primary, sub);
  2421.  
  2422.     { Gets the language data }
  2423.  
  2424.     GetLanguageData(FActiveLanguage, FLanguageData);
  2425.     if FBinding = ivbiLocaleToLanguage then
  2426.     begin
  2427.       if FOriginalLanguage = LANG_SYSTEM then
  2428.         FLanguageData.ActiveSub := IvGetSubFromLocale(CheckLocale(
  2429.           GetSystemDefaultLCID,
  2430.           FLanguageData.DefaultLocale))
  2431.       else
  2432.         FLanguageData.ActiveSub := IvGetSubFromLocale(CheckLocale(
  2433.           GetUserDefaultLCID,
  2434.           FLanguageData.DefaultLocale));
  2435.     end;
  2436.   end;
  2437.  
  2438.   FLanguageLocale := FLanguageData.ActiveLocale;
  2439.  
  2440. {$IFNDEF IVPRO}
  2441.   { Checks if Multilizer pro is required }
  2442.  
  2443.   if {(FEdition = edStandard) and }IvDoesLanguageRequirePro(FLanguageData.Primary) then
  2444.     raise EIvMulti.Create(
  2445.       'Professional edition of Multilizer is required for ' + FLanguageData.EnglishName);
  2446. {$ENDIF}
  2447.  
  2448. {$IFDEF WIN32}
  2449.   { In the desing state the system support for the language is not checked }
  2450.  
  2451.   if not IsDesignTime then
  2452.   begin
  2453.     case FCheckLevel of
  2454.       ivclSystem:
  2455.         if not IsLanguageSupportedBySystem(FLanguageData) then
  2456.           raise EIvMulti.Create(
  2457.             FLanguageData.EnglishName + ' is not supported by the system');
  2458.  
  2459.       ivclCodePage:
  2460.         if not IsLanguageSupportedByCodePage(FLanguageData) then
  2461.           raise EIvMulti.Create(
  2462.             FLanguageData.EnglishName + ' is not supported by the code page');
  2463.     end;
  2464.   end;
  2465. {$ENDIF}
  2466. end;
  2467.  
  2468. procedure TIvDictionary.InitLocale(locale: Integer);
  2469. begin
  2470.   { Inits the active locale and the locale data }
  2471.  
  2472.   FActiveLocale := DecodeLocale(locale);
  2473.   FLocaleData.Free;
  2474.   FLocaleData := TIvLocale.Create;
  2475.   GetLocaleDataById(FActiveLocale, FLocaleData);
  2476.  
  2477. {$IFNDEF IVPRO}
  2478.   { Checks if Multilizer pro is required }
  2479.  
  2480.   if {(FEdition = edStandard) and }IvDoesLanguageRequirePro(IvGetPrimaryFromLocale(locale)) then
  2481.     raise EIvMulti.Create(
  2482.       'Professional edition of Multilizer is required for this locale (' +
  2483.         IntToStr(IvGetPrimaryFromLocale(FActiveLocale)) + ')');
  2484. {$ENDIF}
  2485.  
  2486. {$IFDEF WIN32}
  2487.   { In the desing state the system support for the locale is not checked }
  2488.  
  2489.   if not IsDesignTime then
  2490.   begin
  2491.     case FCheckLevel of
  2492.       ivclSystem:
  2493.         if not IvIsCodePageSupportedBySystem(FLocaleData.CodePage) then
  2494.           raise EIvMulti.Create(
  2495.             SysUtils.Format('The locale (%d, %d) is not supported by the system',
  2496.             [IvGetPrimaryFromLocale(locale), IvGetSubFromLocale(locale)]));
  2497.  
  2498.       ivclCodePage:
  2499.         if not IsLocaleSupportedByCodePage(FLocaleData) then
  2500.           raise EIvMulti.Create(
  2501.             SysUtils.Format('The locale (%d, %d) is not supported by the current code page',
  2502.             [IvGetPrimaryFromLocale(locale), IvGetSubFromLocale(locale)]));
  2503.     end;
  2504.   end;
  2505. {$ENDIF}
  2506. end;
  2507.  
  2508. function TIvDictionary.GetTranslationCount: Integer;
  2509. begin
  2510.   Result := 0;
  2511. end;
  2512.  
  2513. function TIvDictionary.GetTranslationMode: TIvTranslationMode;
  2514. begin
  2515.   Result := ivtmSingle;
  2516. end;
  2517.  
  2518. function TIvDictionary.TranslateString(
  2519.   const str: String;
  2520.   var translation: String): Boolean;
  2521. begin
  2522.   Result := TranslateContextString(str, '', '', translation);
  2523. end;
  2524.  
  2525. procedure TIvDictionary.TranslateStrings(translations: TList);
  2526. begin
  2527. end;
  2528.  
  2529. procedure TIvDictionary.SetEuro(value: TIvEuro);
  2530. begin
  2531.   FEuro := value;
  2532.   euroUsage := value;
  2533.   CurrencyString := LocaleData.EMUCurrencyString;
  2534. end;
  2535.  
  2536. procedure TIvDictionary.LanguageChanged(languageChanged, localeChanged: Boolean);
  2537. var
  2538.   i, day: Integer;
  2539.   str: String;
  2540.   rect: TRect;
  2541.   winPlacement: TWindowPlacement;
  2542. {$IFNDEF IVIME}
  2543.   size: Integer;
  2544. {$ENDIF}
  2545.  
  2546.   procedure Year2000(var str: String);
  2547.   begin
  2548.     if Pos('yyyy', str) = 0 then
  2549.       Insert('yy', str, Pos('yy', str));
  2550.   end;
  2551.  
  2552. begin
  2553. {$IFDEF IVPRO32}
  2554.   {$IFDEF IVBIDI}
  2555.   { In VCL 4 or later it is enough to set the BidiMode of the application
  2556.     component to match the current reading order. }
  2557.  
  2558.   if LanguageData.CharsetType = ivcsBiDirectional then
  2559.     Application.BidiMode := bdRightToLeft
  2560.   else
  2561.     Application.BidiMode := bdLeftToRight;
  2562.   {$ENDIF}
  2563. {$ENDIF}
  2564.  
  2565.   if localeChanged then
  2566.   begin
  2567. {$IFDEF WIN32}
  2568.     SetThreadLocale(FActiveLocale);
  2569. {$ENDIF}
  2570.  
  2571.     if ivdoUpdateLocaleVariables in FOptions then
  2572.     begin
  2573.       { Updates standard VCL locale variables }
  2574.  
  2575. {$IFDEF IVWIDE}
  2576.       SysLocale.DefaultLCID := FLocaleData.Locale;
  2577.       SysLocale.PriLangID := FLocaleData.Primary;
  2578.       SysLocale.SubLangID := FLocaleData.Sub;
  2579.       SysLocale.FarEast := GetSystemMetrics(SM_DBCSENABLED) <> 0;
  2580. {$ENDIF}
  2581.  
  2582.       CurrencyString := FLocaleData.EMUCurrencyString;
  2583.       CurrencyFormat := Byte(FLocaleData.CurrencyFormat);
  2584.       NegCurrFormat := Byte(FLocaleData.NegCurrFormat);
  2585.       ThousandSeparator := FLocaleData.ThousandSeparator;
  2586.       DecimalSeparator := FLocaleData.DecimalSeparator;
  2587.       CurrencyDecimals := FLocaleData.CurrencyDecimals;
  2588.  
  2589.       DateSeparator := FLocaleData.DateSeparator;
  2590.       ShortDateFormat := FLocaleData.ShortDateFormat;
  2591.       LongDateFormat := FLocaleData.LongDateFormat;
  2592.  
  2593.       { ML can correct the year format short date using a four digits instead
  2594.         of two digits }
  2595.  
  2596.       if ivdoYear2000 in FOptions then
  2597.       begin
  2598.         Year2000(ShortDateFormat);
  2599.         Year2000(LongDateFormat);
  2600.       end;
  2601.  
  2602.       str := FLocaleData.TimeSeparator;
  2603.       if str <> '' then
  2604.         TimeSeparator := str[1]
  2605.       else
  2606.         TimeSeparator := ':';
  2607.       TimeAMString := FLocaleData.TimeAMString;
  2608.       TimePMString := FLocaleData.TimePMString;
  2609.  
  2610.       SetTimeFormats(
  2611.         FLocaleData.TimeFormat,
  2612.         FLocaleData.TimeMarkPosition,
  2613.         FLocaleData.TimeLeadingZeros,
  2614.         ShortTimeFormat,
  2615.         LongTimeFormat);
  2616.  
  2617.       for i := 1 to 12 do
  2618.       begin
  2619.         ShortMonthNames[i] := FLocaleData.ShortMonthNames[i];
  2620.         LongMonthNames[i] := FLocaleData.LongMonthNames[i];
  2621.       end;
  2622.  
  2623.       for i := 1 to 7 do
  2624.       begin
  2625.         { In VCL XxxxDayNames[1] is not Monday but Sunday }
  2626.  
  2627.         if i = 7 then
  2628.           day := 1
  2629.         else
  2630.           day := i + 1;
  2631.         ShortDayNames[day] := FLocaleData.ShortDayNames[i];
  2632.         LongDayNames[day] := FLocaleData.LongDayNames[i];
  2633.       end;
  2634.     end;
  2635.   end;
  2636.  
  2637.   { Makes all translators to translate themselves }
  2638.  
  2639.   if ivdoAutoTranslate in FOptions then
  2640.     for i := 0 to FTranslators.Count - 1 do
  2641.       TIvCustomTranslator(FTranslators.Items[i]).LanguageChanged(languageChanged, localeChanged);
  2642.  
  2643.   { Calls the events }
  2644.  
  2645.   if languageChanged and Assigned(FOnLanguageChange) then
  2646.     FOnLanguageChange(Self);
  2647.   if localeChanged and Assigned(FOnLocaleChange) then
  2648.     FOnLocaleChange(Self);
  2649.  
  2650.   { Force MDI to put back the system menu of a maximized child }
  2651.  
  2652.   if languageChanged and (Application.MainForm <> nil) and (Application.MainForm is TForm) then
  2653.   begin
  2654.     with TForm(Application.MainForm) do
  2655.     begin
  2656.       if (FormStyle = fsMDIForm) and (ActiveMDIChild <> nil) and (ActiveMDIChild.WindowState = wsMaximized) then
  2657.       begin
  2658.         { Save window dimension in normal state }
  2659.  
  2660.         if MDIChildCount = 1 then
  2661.         begin
  2662.           GetWindowPlacement(ActiveMDIChild.Handle, @winPlacement);
  2663.           rect := winPlacement.rcNormalPosition;
  2664.         end;
  2665.  
  2666. {$IFDEF IVIME}
  2667.         SendMessage(ActiveMDIChild.Handle, CM_RECREATEWND, 0, 0);
  2668. {$ELSE}
  2669.         size := ActiveMDIChild.ClientWidth + (Longint(ActiveMDIChild.ClientHeight) shl 16);
  2670.         SendMessage(ActiveMDIChild.Handle, WM_SIZE, SIZE_RESTORED, size);
  2671.         SendMessage(ActiveMDIChild.Handle, WM_SIZE, SIZE_MAXIMIZED, size);
  2672. {$ENDIF}
  2673.  
  2674.         { Set saved dimension after recreating window }
  2675.  
  2676.         if MDIChildCount = 1 then
  2677.         begin
  2678.           GetWindowPlacement(ActiveMDIChild.Handle, @winPlacement);
  2679.           winPlacement.rcNormalPosition := rect;
  2680.           SetWindowPlacement(ActiveMDIChild.Handle, @winPlacement);
  2681.         end;
  2682.       end;
  2683.     end;
  2684.   end;
  2685. end;
  2686.  
  2687. function TIvDictionary.GetDefaultLanguage: Integer;
  2688. var
  2689.   i, start: Integer;
  2690. begin
  2691.   { Gets the first language of the dictionary }
  2692.  
  2693.   if (LanguageCount = 0) or (Languages[0].Primary <> LANG_NEUTRAL) then
  2694.     start := 0
  2695.   else
  2696.     start := 1;
  2697.  
  2698.   { Gets the first language of the dictionary that is compatible with the
  2699.     current check level. }
  2700.  
  2701. {$IFDEF WIN32}
  2702.   Result := -1;
  2703.   for i := start to LanguageCount - 1 do
  2704.   begin
  2705.     case FCheckLevel of
  2706.       ivclNone:
  2707.         Result := i;
  2708.  
  2709.       ivclSystem:
  2710.         if IsLanguageSupportedBySystem(Languages[i]) then
  2711.           Result := i;
  2712.  
  2713.       ivclCodePage:
  2714.         if IsLanguageSupportedByCodePage(Languages[i]) then
  2715.           Result := i;
  2716.     end;
  2717.  
  2718.     if Result >= 0 then
  2719.       Break;
  2720.   end;
  2721. {$ELSE}
  2722.   Result := start;
  2723. {$ENDIF}
  2724. end;
  2725.  
  2726. function TIvDictionary.DecodeLocale(value: Integer): Integer;
  2727. begin
  2728.   if value = IvMakeLcId(IvMakeLangId(LANG_NEUTRAL, SUBLANG_DEFAULT), SORT_DEFAULT) then
  2729.     Result := GetUserDefaultLCID
  2730.   else if value = IvMakeLcId(IvMakeLangId(LANG_NEUTRAL, SUBLANG_SYS_DEFAULT), SORT_DEFAULT) then
  2731.     Result := GetSystemDefaultLCID
  2732.   else
  2733.     Result := value;
  2734. end;
  2735.  
  2736. function TIvDictionary.GetTranslatorCount: Integer;
  2737. begin
  2738.   Result := FTranslators.Count;
  2739. end;
  2740.  
  2741. function TIvDictionary.GetTranslator(i: Integer): TIvCustomTranslator;
  2742. begin
  2743.   Result := FTranslators.Items[i];
  2744. end;
  2745.  
  2746. function TIvDictionary.GetLanguage(i: Integer): TIvLanguage;
  2747. begin
  2748.   if i >= LanguageCount then
  2749.     raise ERangeError.Create('Out of language range');
  2750.  
  2751.   if i = FActiveLanguage then
  2752.     Result := FLanguageData
  2753.   else
  2754.   begin
  2755.     FTempLanguageData.Free;
  2756.     FTempLanguageData := TIvLanguage.Create;
  2757.     GetLanguageData(i, FTempLanguageData);
  2758.     Result := FTempLanguageData;
  2759.   end;
  2760. end;
  2761.  
  2762. function TIvDictionary.GetLocale(i: Integer): TIvLocale;
  2763. begin
  2764.   if i >= LocaleCount then
  2765.     raise ERangeError.Create('Out of locale range');
  2766.  
  2767.   FTempLocaleData.Free;
  2768.   FTempLocaleData := TIvLocale.Create;
  2769.   GetLocaleData(i, FTempLocaleData);
  2770.   Result := FTempLocaleData;
  2771. end;
  2772.  
  2773. function TIvDictionary.LocaleToLanguage(locale: Integer): Integer;
  2774. var
  2775.   i, j, primary, sub: Integer;
  2776.   list: TList;
  2777.   language: TIvLanguage;
  2778. begin
  2779.   if locale = IvMakeLcId(IvMakeLangId(LANG_NEUTRAL, SUBLANG_NEUTRAL), SORT_DEFAULT) then
  2780.   begin
  2781.     Result := 0;
  2782.     Exit;
  2783.   end;
  2784.  
  2785.   locale := DecodeLocale(locale);
  2786.   primary := IvGetPrimaryFromLocale(locale);
  2787.   sub := IvGetSubFromLocale(locale);
  2788.  
  2789.   { Gets all languages }
  2790.  
  2791.   list := TList.Create;
  2792.   GetLanguageDatas(list);
  2793.   try
  2794.     { Tries exact match }
  2795.  
  2796.     for i := 0 to list.Count - 1 do
  2797.     begin
  2798.       language := TIvLanguage(list[i]);
  2799.  
  2800.       if language.Primary = primary then
  2801.       begin
  2802.         { If either the default sub or one of the subs contains the
  2803.           given sub this language is used. }
  2804.  
  2805.         if language.DefaultSub = sub then
  2806.         begin
  2807.           Result := i;
  2808.           Exit;
  2809.         end;
  2810.  
  2811.         for j := 0 to language.SubCount - 1 do
  2812.           if sub = language.Subs[j] then
  2813.           begin
  2814.             Result := i;
  2815.             Exit;
  2816.           end;
  2817.       end;
  2818.     end;
  2819.  
  2820.     { Tries neutral match }
  2821.  
  2822.     for i := 0 to list.Count - 1 do
  2823.     begin
  2824.       language := TIvLanguage(list[i]);
  2825.  
  2826.       if (language.Primary = primary) and
  2827.         ((language.SubCount = 0) or (language.Subs[0] = SUBLANG_NEUTRAL)) then
  2828.       begin
  2829.         Result := i;
  2830.         Exit;
  2831.       end;
  2832.     end;
  2833.  
  2834.     { Tries primary only match }
  2835.  
  2836.     for i := 0 to list.Count - 1 do
  2837.     begin
  2838.       language := TIvLanguage(list[i]);
  2839.  
  2840.       if language.Primary = primary then
  2841.       begin
  2842.         Result := i;
  2843.         Exit;
  2844.       end;
  2845.     end;
  2846.  
  2847.     { No language matches the locale }
  2848.  
  2849.     Result := -1;
  2850.   finally
  2851.     FreeList(list);
  2852.   end;
  2853. end;
  2854.  
  2855. function TIvDictionary.IsLocaleSupported(locale: Integer): Boolean;
  2856. var
  2857.   i: Integer;
  2858.   list: TList;
  2859. begin
  2860.   Result := False;
  2861.  
  2862.   list := TList.Create;
  2863.   GetLocaleIds(list);
  2864.  
  2865.   for i := 0 to list.Count - 1 do
  2866.     if Integer(list[i]) = locale then
  2867.     begin
  2868.       Result := True;
  2869.       Break;
  2870.     end;
  2871.  
  2872.   list.Free;
  2873. end;
  2874.  
  2875. {$IFDEF WIN32}
  2876. class function TIvDictionary.GetCompareOptions(ignoreCase, ignoreSymbols: Boolean): Integer;
  2877. begin
  2878.   Result := 0;
  2879.   if ignoreCase then
  2880.     Result := NORM_IGNORECASE;
  2881.   //if ignoreSymbols then
  2882.   //  Result := NORM_IGNORESYMBOLS;
  2883. end;
  2884. {$ENDIF}
  2885.  
  2886. class function TIvDictionary.IvCompareText(
  2887.   const s1, s2: String;
  2888.   locale: Integer;
  2889.   ignoreSymbols: Boolean): Integer;
  2890. begin
  2891. {$IFDEF WIN32}
  2892.   Result := CompareString(
  2893.     locale,
  2894.     GetCompareOptions(True, ignoreSymbols),
  2895.     PChar(s1),
  2896.     Length(s1),
  2897.     PChar(s2),
  2898.     Length(s2)) - 2;
  2899. {$ELSE}
  2900.   Result := AnsiCompareText(s1, s2);
  2901. {$ENDIF}
  2902. end;
  2903.  
  2904. class function TIvDictionary.IvCompareStr(
  2905.   const s1, s2: String;
  2906.   locale: Integer;
  2907.   ignoreSymbols: Boolean): Integer;
  2908. begin
  2909. {$IFDEF WIN32}
  2910.   Result := CompareString(
  2911.     locale,
  2912.     GetCompareOptions(False, ignoreSymbols),
  2913.     PChar(s1),
  2914.     Length(s1),
  2915.     PChar(s2),
  2916.     Length(s2)) - 2;
  2917. {$ELSE}
  2918.   Result := AnsiCompareStr(s1, s2);
  2919. {$ENDIF}
  2920. end;
  2921.  
  2922. class function TIvDictionary.IvCompareBinary(const s1, s2: String): Integer;
  2923. var
  2924.   i, len, len1, len2: Integer;
  2925. begin
  2926.   len1 := Length(s1);
  2927.   len2 := Length(s2);
  2928.   if len1 < len2 then
  2929.     len := len1
  2930.   else
  2931.     len := len2;
  2932.  
  2933.   for i := 1 to len do
  2934.   begin
  2935.     if s1[i] < s2[i] then
  2936.     begin
  2937.       Result := -1;
  2938.       Exit;
  2939.     end
  2940.     else if s1[i] > s2[i] then
  2941.     begin
  2942.       Result := 1;
  2943.       Exit;
  2944.     end;
  2945.   end;
  2946.  
  2947.   if len1 = len2 then
  2948.     Result := 0
  2949.   else if len1 < len2 then
  2950.     Result := -1
  2951.   else
  2952.     Result := 1;
  2953. end;
  2954.  
  2955. {$IFDEF IVWIDE}
  2956. function IsNT: Boolean;
  2957. var
  2958.   versionInfo: TOSVersionInfo;
  2959. begin
  2960.   versionInfo.dwOSVersionInfoSize := Sizeof(versionInfo);
  2961.   GetVersionEx(versionInfo);
  2962.   Result := versionInfo.dwPlatformId = VER_PLATFORM_WIN32_NT;
  2963. end;
  2964.  
  2965. class function TIvDictionary.IvWideCompareText(
  2966.   const s1, s2: WideString;
  2967.   locale: Integer;
  2968.   ignoreSymbols: Boolean): Integer;
  2969. var
  2970.   codePage: Integer;
  2971. begin
  2972.   if IsNT then
  2973.     Result := CompareStringW(
  2974.       locale,
  2975.       GetCompareOptions(True, ignoreSymbols),
  2976.       PWideChar(s1),
  2977.       Length(s1),
  2978.       PWideChar(s2),
  2979.       Length(s2)) - 2
  2980.   else
  2981.   begin
  2982.     codePage := IvLangIdToCodePage(locale);
  2983.     Result := IvCompareText(
  2984.       IvWStrToStr(s1, codePage),
  2985.       IvWStrToStr(s2, codePage),
  2986.       locale,
  2987.       ignoreSymbols);
  2988.   end;
  2989. end;
  2990.  
  2991. class function TIvDictionary.IvWideCompareStr(
  2992.   const s1, s2: WideString;
  2993.   locale: Integer;
  2994.   ignoreSymbols: Boolean): Integer;
  2995. var
  2996.   codePage: Integer;
  2997. begin
  2998.   if IsNT then
  2999.     Result := CompareStringW(
  3000.       locale,
  3001.       GetCompareOptions(False, ignoreSymbols),
  3002.       PWideChar(s1),
  3003.       Length(s1),
  3004.       PWideChar(s2),
  3005.       Length(s2)) - 2
  3006.   else
  3007.   begin
  3008.     codePage := IvLangIdToCodePage(locale);
  3009.     Result := IvCompareStr(
  3010.       IvWStrToStr(s1, codePage),
  3011.       IvWStrToStr(s2, codePage),
  3012.       locale,
  3013.       ignoreSymbols);
  3014.   end;
  3015. end;
  3016.  
  3017. class function TIvDictionary.IvWideCompareBinary(const s1, s2: WideString): Integer;
  3018. var
  3019.   i, len, len1, len2: Integer;
  3020. begin
  3021.   len1 := Length(s1);
  3022.   len2 := Length(s2);
  3023.   if len1 < len2 then
  3024.     len := len1
  3025.   else
  3026.     len := len2;
  3027.  
  3028.   for i := 1 to len do
  3029.   begin
  3030.     if s1[i] < s2[i] then
  3031.     begin
  3032.       Result := -1;
  3033.       Exit;
  3034.     end
  3035.     else if s1[i] > s2[i] then
  3036.     begin
  3037.       Result := 1;
  3038.       Exit;
  3039.     end;
  3040.   end;
  3041.  
  3042.   if len1 = len2 then
  3043.     Result := 0
  3044.   else if len1 < len2 then
  3045.     Result := -1
  3046.   else
  3047.     Result := 1;
  3048. end;
  3049. {$ENDIF}
  3050.  
  3051. function IvLangIdToCodePage(langId: Integer): Integer;
  3052. begin
  3053. {$IFDEF WIN32}
  3054.   Result := StrToInt(GetLocaleStr(IvMakeLcId(langId, 0), LOCALE_IDEFAULTANSICODEPAGE, '0'));
  3055.   if Result > 0 then
  3056.     Exit;
  3057. {$ENDIF}
  3058.  
  3059.   case IvGetPrimaryFromLocale(langId) of
  3060.     LANG_THAI:
  3061.       Result := THAI_CP_C;
  3062.  
  3063.     LANG_JAPANESE:
  3064.       Result := JAPANESE_CP_C;
  3065.  
  3066.     LANG_KOREAN:
  3067.       Result := KOREAN_CP_C;
  3068.  
  3069.     LANG_CHINESE:
  3070.       case IvGetSubFromLocale(langId) of
  3071.         SUBLANG_CHINESE_TRADITIONAL,
  3072.         SUBLANG_CHINESE_HONGKONG:
  3073.           Result := TRADITIONAL_CHINESE_CP_C
  3074.       else
  3075.         Result := SIMPLIFIED_CHINESE_CP_C;
  3076.       end;
  3077.  
  3078.     LANG_ALBANIAN,
  3079.     LANG_CZECH,
  3080.     LANG_HUNGARIAN,
  3081.     LANG_POLISH,
  3082.     LANG_ROMANIAN,
  3083.     LANG_SLOVAK,
  3084.     LANG_SLOVENIAN:
  3085.       Result := EAST_EUROPE_CP_C;
  3086.  
  3087.     LANG_BELARUSIAN,
  3088.     LANG_BULGARIAN,
  3089.     LANG_RUSSIAN,
  3090.     LANG_UKRAINIAN:
  3091.       Result := CYRILLIC_CP_C;
  3092.  
  3093.     {LANG_SERBIAN,}
  3094.     LANG_CROATIAN:
  3095.       case IvGetSubFromLocale(langId) of
  3096.         SUBLANG_DEFAULT,
  3097.         SUBLANG_SERBIAN_LATIN:
  3098.           Result := EAST_EUROPE_CP_C;
  3099.       else
  3100.         Result := CYRILLIC_CP_C;
  3101.       end;
  3102.  
  3103.     LANG_GREEK:
  3104.       Result := GREEK_CP_C;
  3105.  
  3106.     LANG_TURKISH:
  3107.       Result := TURKISH_CP_C;
  3108.  
  3109.     LANG_HEBREW:
  3110.       Result := HEBREW_CP_C;
  3111.  
  3112.     LANG_FARSI,
  3113.     LANG_ARABIC:
  3114.       Result := ARABIC_CP_C;
  3115.  
  3116.     LANG_ESTONIAN,
  3117.     LANG_LATVIAN,
  3118.     LANG_LITHUANIAN:
  3119.       Result := BALTIC_CP_C;
  3120.  
  3121.     LANG_VIETNAMESE:
  3122.       Result := VIETNAMESE_CP_C;
  3123.   else
  3124.     Result := WESTERN_CP_C;
  3125.   end;
  3126. end;
  3127.  
  3128. {$IFDEF WIN32}
  3129. class function TIvDictionary.IsLanguageSupportedBySystem(language: TIvLanguage): Boolean;
  3130. begin
  3131.   { Language is supported by system if it uses only standard ASCII or it uses
  3132.     the same code page as the system. }
  3133.  
  3134.   Result :=
  3135.     (language.Primary = LANG_NEUTRAL) or
  3136.     (language.Primary = LANG_ENGLISH) or
  3137.     (language.Primary = LANG_INDONESIAN) or
  3138.     (ivloPureASCII in language.Options) or
  3139.     IvIsCodePageSupportedBySystem(language.CodePage);
  3140. end;
  3141.  
  3142. class function TIvDictionary.IsLanguageSupportedByCodePage(language: TIvLanguage): Boolean;
  3143. begin
  3144.   { Language is supported by the code page if it uses only standard ASCII or
  3145.     it is compatible with the current code page. }
  3146.  
  3147.   Result :=
  3148.     (language.Primary = LANG_NEUTRAL) or
  3149.     (language.Primary = LANG_ENGLISH) or
  3150.     (language.Primary = LANG_INDONESIAN) or
  3151.     (ivloPureASCII in language.Options) or
  3152.     (language.CodePage = 0) or
  3153.     (language.CodePage = Integer(GetACP));
  3154. end;
  3155.  
  3156. class function TIvDictionary.IsLocaleSupportedBySystem(locale: TIvLocale): Boolean;
  3157. begin
  3158.   { Locale is supported by system if it uses only standard ASCII or it uses
  3159.     the same code page as the system. }
  3160.  
  3161.   Result :=
  3162.     (locale.Primary = LANG_NEUTRAL) or
  3163.     (locale.Primary = LANG_ENGLISH) or
  3164.     (locale.Primary = LANG_INDONESIAN) or
  3165.     IvIsCodePageSupportedBySystem(locale.CodePage);
  3166. end;
  3167.  
  3168. class function TIvDictionary.IsLocaleSupportedByCodePage(locale: TIvLocale): Boolean;
  3169. begin
  3170.   { Locale is supported by the code page if it uses only standard ASCII or
  3171.     it is compatible with the current code page. }
  3172.  
  3173.   Result :=
  3174.     (locale.Primary = LANG_NEUTRAL) or
  3175.     (locale.Primary = LANG_ENGLISH) or
  3176.     (locale.Primary = LANG_INDONESIAN) or
  3177.     (locale.CodePage = Integer(GetACP));
  3178. end;
  3179.  
  3180. function IvIsCodePageSupportedBySystem(codePage: Integer): Boolean;
  3181.  
  3182.   function EnumCodePages(locale: PChar): Integer; stdcall;
  3183.   begin
  3184.     if StrToInt(locale) = enumInteger then
  3185.       supported := True;
  3186.     Result := 1;
  3187.   end;
  3188.  
  3189. begin
  3190.   if codePage = 0 then
  3191.     Result := True
  3192.   else
  3193.   begin
  3194.     enumInteger := codePage;
  3195.     supported := False;
  3196.     EnumSystemCodePages(@EnumCodePages, CP_SUPPORTED);
  3197.     Result := supported;
  3198.   end;
  3199. end;
  3200.  
  3201. function IvIsLocaleSupportedByCodePage(locale: Integer): Boolean;
  3202. var
  3203.   primary, codePage: Integer;
  3204. begin
  3205.   primary := IvGetPrimaryFromLocale(locale);
  3206.   if primary = LANG_NEUTRAL then
  3207.     Result := True
  3208.   else
  3209.   begin
  3210.     codePage := StrToInt(GetLocaleStr(locale, LOCALE_IDEFAULTANSICODEPAGE, '0'));
  3211.     Result :=
  3212.       (primary = LANG_ENGLISH) or
  3213.       (primary = LANG_INDONESIAN) or
  3214.       (Integer(GetACP) = codePage);
  3215.   end;
  3216. end;
  3217.  
  3218. function TIvDictionary.CompareText(const s1, s2: String): Integer;
  3219. begin
  3220.   Result := IvCompareText(s1, s2, LanguageLocale, False);
  3221. end;
  3222.  
  3223. function TIvDictionary.CompareStr(const s1, s2: String): Integer;
  3224. begin
  3225.   Result := IvCompareStr(s1, s2, LanguageLocale, False);
  3226. end;
  3227. {$ENDIF}
  3228.  
  3229. function TIvDictionary.IsOpen: Boolean;
  3230. begin
  3231.   Result := FOpen;
  3232. end;
  3233.  
  3234. function TIvDictionary.CanBeOpened: Boolean;
  3235. begin
  3236.   Result := True;
  3237. end;
  3238.  
  3239. procedure TIvDictionary.Open;
  3240. var
  3241.   language: Integer;
  3242. {$IFDEF IVWIDE}
  3243.   {$IFNDEF IVVB}
  3244.   protect: Integer;
  3245.   {$ENDIF}
  3246. {$ENDIF}
  3247. begin
  3248.   if IsOpen or not CanBeOpened then
  3249.     Exit;
  3250.  
  3251.   FOriginalLanguage := FLanguage;
  3252.   try
  3253.     { Sets the initial language and locale }
  3254.  
  3255.     case FBinding of
  3256.       ivbiNone:
  3257.       begin
  3258.         { Language and locale are not connected. Sets both separately.}
  3259.  
  3260.         InitLanguage(FLanguage);
  3261.         InitLocale(FLocale);
  3262.       end;
  3263.  
  3264.       ivbiLocaleToLanguage:
  3265.       begin
  3266.         { Locale is connected to the language. Sets the language first and
  3267.           sets then the locale to the default locale of the language. }
  3268.  
  3269.         InitLanguage(FLanguage);
  3270.         InitLocale(FLanguageData.ActiveLocale);
  3271.       end;
  3272.  
  3273.       ivbiLanguageToLocale:
  3274.       begin
  3275.         { Language is connected to the locale. Sets the locale first. Then
  3276.           check if the dictionary contains the language of the locale. If does
  3277.           sets that language on. Otherwise sets the default language. }
  3278.  
  3279.         InitLocale(FLocale);
  3280.  
  3281.         language := LocaleToLanguage(FActiveLocale);
  3282.         if language < 0 then
  3283.           InitLanguage(DefaultLanguage)
  3284.         else
  3285.         begin
  3286.           { The InitLanguage sets the language locale to the default locale of
  3287.             the language.
  3288.             However, in this case the active locale is used. }
  3289.  
  3290.           InitLanguage(language);
  3291.           FLanguageLocale := FActiveLocale;
  3292.         end;
  3293.       end;
  3294.     end;
  3295.  
  3296. {$IFDEF IVWIDE}
  3297.   {$IFNDEF IVVB}
  3298.     { Automatic resource string translation is turned on only when the
  3299.       application is statically linked (e.g. does not use packages) }
  3300.  
  3301.     if not IsDesignTime and
  3302.       not loadResStringChanged and
  3303.       (ivdoTranslateResourceStrings in FOptions) and
  3304.       (LibModuleList.Next = nil) then
  3305.     begin
  3306.       VirtualProtect(@LoadResString, 34, PAGE_READWRITE, @protect);
  3307.       Move((@LoadResString)^, resStringBuffer, 34);
  3308.       Move((@IvLoadResString)^, (@LoadResString)^, 34);
  3309.       VirtualProtect(@LoadResString, 34, protect, @protect);
  3310.  
  3311.       VirtualProtect(@ShortCutToText, 34, PAGE_READWRITE, @protect);
  3312.       Move((@ShortCutToText)^, shortCutBuffer, 34);
  3313.       Move((@IvShortCutToText)^, (@ShortCutToText)^, 34);
  3314.       VirtualProtect(@ShortCutToText, 34, protect, @protect);
  3315.  
  3316.       loadResStringChanged := True;
  3317.     end;
  3318.   {$ENDIF}
  3319. {$ENDIF}
  3320.  
  3321. {$IFDEF IVBINARY}
  3322.     if FDictionaryCode = Integer(liLimited) then
  3323.     begin
  3324.       if LanguageCount > LIMITED_VERSION_LANGAUGE_COUNT_C then
  3325.       begin
  3326.         Close;
  3327.         raise EIvMulti.Create(Format(
  3328.           'The maximum language count of the limited version is %d.',
  3329.           [LIMITED_VERSION_LANGAUGE_COUNT_C]));
  3330.       end;
  3331.  
  3332.       if TranslationCount > LIMITED_VERSION_TRANSLATION_COUNT_C then
  3333.       begin
  3334.         Close;
  3335.         raise EIvMulti.Create(Format(
  3336.           'The maximum translation count of the limited version is %d.',
  3337.           [LIMITED_VERSION_TRANSLATION_COUNT_C]));
  3338.       end;
  3339.     end;
  3340. {$ENDIF}
  3341.  
  3342.     { Updates the language }
  3343.  
  3344.     FOpen := True; { This must be called before LanguageChanged }
  3345.     LanguageChanged(True, True);
  3346.   except
  3347.     Close;
  3348.     raise;
  3349.   end;
  3350. end;
  3351.  
  3352. procedure TIvDictionary.Close;
  3353. {$IFDEF IVWIDE}
  3354.   {$IFNDEF IVVB}
  3355. var
  3356.   protect: Integer;
  3357.   {$ENDIF}
  3358. {$ENDIF}
  3359. begin
  3360. {$IFDEF IVWIDE}
  3361.   {$IFNDEF IVVB}
  3362.   if not IsDesignTime and loadResStringChanged then
  3363.   begin
  3364.     VirtualProtect(@LoadResString, 34, PAGE_READWRITE, @protect);
  3365.     Move(resStringBuffer, (@LoadResString)^, 34);
  3366.     VirtualProtect(@LoadResString, 34, protect, @protect);
  3367.  
  3368.     VirtualProtect(@ShortCutToText, 34, PAGE_READWRITE, @protect);
  3369.     Move(shortCutBuffer, (@ShortCutToText)^, 34);
  3370.     VirtualProtect(@ShortCutToText, 34, protect, @protect);
  3371.  
  3372.     loadResStringChanged := False;
  3373.   end;
  3374.   {$ENDIF}
  3375. {$ENDIF}
  3376.  
  3377.   UnbindTranslators;
  3378.   FOpen := False;
  3379. end;
  3380.  
  3381. procedure TIvDictionary.UnbindTranslators;
  3382. begin
  3383.   { Unbinds all transaltors from the dictionary }
  3384.  
  3385.   while FTranslators.Count > 0 do
  3386.     TIvCustomTranslator(FTranslators[0]).Unbind;
  3387. end;
  3388.  
  3389. procedure TIvDictionary.AddTranslator(translator: TIvCustomTranslator);
  3390. var
  3391.   i: Integer;
  3392. begin
  3393.   { Adds the given translator to the translator list if it does not
  3394.     already exist there. }
  3395.  
  3396.   for i := 0 to FTranslators.Count - 1 do
  3397.     if FTranslators.Items[i] = translator then
  3398.       Exit;
  3399.   FTranslators.Add(translator);
  3400. end;
  3401.  
  3402. procedure TIvDictionary.RemoveTranslator(translator: TIvCustomTranslator);
  3403. begin
  3404.   { Removes the given translator from the translator list. }
  3405.  
  3406.   FTranslators.Remove(translator);
  3407. end;
  3408.  
  3409. function TIvDictionary.DoesTranslationExist(const str: String): Boolean;
  3410. var
  3411.   translation: String;
  3412. begin
  3413.   Result := TranslateString(str, translation);
  3414. end;
  3415.  
  3416. function TIvDictionary.DoesContextTranslationExist(const str, form, component: String): Boolean;
  3417. var
  3418.   translation: String;
  3419. begin
  3420.   Result := TranslateContextString(str, form, component, translation);
  3421. end;
  3422.  
  3423. function Translate(const str: String): String;
  3424. begin
  3425.   if Dictionaries.Count = 0 then
  3426.     Result := str
  3427.   else
  3428.     Result := Dictionaries[0].Translate(str);
  3429. end;
  3430.  
  3431. function TranslateContext(const str, form, component: String): String;
  3432. begin
  3433.   if Dictionaries.Count = 0 then
  3434.     Result := str
  3435.   else
  3436.     Result := Dictionaries[0].TranslateContext(str, form, component);
  3437. end;
  3438.  
  3439. function GetDefaultDictionary: TIvDictionary;
  3440. begin
  3441.   if Dictionaries.Count = 0 then
  3442.     Result := nil
  3443.   else
  3444.     Result := Dictionaries[0];
  3445. end;
  3446.  
  3447. function TIvDictionary.Translate(const str: String): String;
  3448. var
  3449.   ok: Boolean;
  3450.   translation: String;
  3451. begin
  3452.   Result := str;
  3453.   if Self = nil then
  3454.     Exit;
  3455.  
  3456.   if str <> '' then
  3457.   begin
  3458.     ok := TranslateString(str, translation);
  3459.     Result := CheckTranslation(str, translation, ok);
  3460.   end;
  3461. end;
  3462.  
  3463. function TIvDictionary.TranslateContext(const str, form, component: String): String;
  3464. var
  3465.   ok: Boolean;
  3466.   translation: String;
  3467. begin
  3468.   Result := str;
  3469.   if Self = nil then
  3470.     Exit;
  3471.  
  3472.   { Translates the string }
  3473.  
  3474.   if str = '' then
  3475.   begin
  3476.     ok := True;
  3477.     translation := '';
  3478.   end
  3479.   else if ContextType = [] then
  3480.     ok := TranslateString(str, translation)
  3481.   else
  3482.   begin
  3483.     { Tries first to translate with the context information.
  3484.       If not found translates without the context information. }
  3485.  
  3486.     ok := TranslateContextString(str, form, component, translation);
  3487.     if not ok then
  3488.       ok := TranslateString(str, translation);
  3489.   end;
  3490.  
  3491.   Result := CheckTranslation(str, translation, ok);
  3492. end;
  3493.  
  3494. function TIvDictionary.CheckTranslation(
  3495.   const native, translation: String;
  3496.   ok: Boolean): String;
  3497. const
  3498.   TAG_C = '@';
  3499. begin
  3500.   if ok then
  3501.   begin
  3502.     { The translation was found from the dictionary. }
  3503.  
  3504.     if translation <> '' then
  3505.       Result := translation
  3506.     else
  3507.       case FMissingTranslation of
  3508.         ivmtUseNative:
  3509.           Result := native;
  3510.  
  3511.         ivmtUseNull:
  3512.           Result := '';
  3513.  
  3514.         ivmtTagNative:
  3515.           Result := TAG_C + native + TAG_C;
  3516.  
  3517.         ivmtRaiseException:
  3518.           raise EIvMulti.Create('Translation for the word "' + native + '" is missing')
  3519.       end;
  3520.   end
  3521.   else
  3522.   begin
  3523.     { The translation was not found from the dictionary. }
  3524.  
  3525.     case FMissingTranslation of
  3526.       ivmtUseNative:
  3527.         Result := native;
  3528.  
  3529.       ivmtUseNull:
  3530.         Result := '';
  3531.  
  3532.       ivmtTagNative:
  3533.         Result := TAG_C + native + TAG_C;
  3534.  
  3535.       ivmtRaiseException:
  3536.         raise EIvMulti.Create('Dictionary does not contain a translation for the word "' + native + '"')
  3537.     end;
  3538.   end;
  3539. end;
  3540.  
  3541. class function TIvDictionary.ComposeLanguageName(
  3542.   language: String;
  3543.   primary, codePage: Integer;
  3544.   translate: Boolean;
  3545.   dictionary: TIvDictionary): String;
  3546. var
  3547.   str: String;
  3548.   parser: TIvStringParser;
  3549. begin
  3550.   if translate and (dictionary = nil) then
  3551.     dictionary := GetDefaultDictionary;
  3552.  
  3553.   parser := TIvStringParser.CreateValue(language, ' ');
  3554.  
  3555.   if (primary = LANG_NORWEGIAN) or (primary = LANG_SPANISH) then
  3556.   begin
  3557.     parser.Separator := ' ';
  3558.     Result := parser.GetString;
  3559.     if translate then
  3560.       Result := dictionary.Translate(Result);
  3561.   end
  3562.   else if (primary = LANG_CHINESE) or (primary = LANG_KOREAN) then
  3563.   begin
  3564.     parser.Separator := '(';
  3565.     Result := parser.GetString;
  3566.     if translate then
  3567.       Result := dictionary.Translate(Result);
  3568.     if primary = LANG_CHINESE then
  3569.     begin
  3570.       if codePage = TRADITIONAL_CHINESE_CP_C then
  3571.         str := 'Traditional'
  3572.       else
  3573.         str := 'Simplified';
  3574.       if translate then
  3575.         str := dictionary.Translate(str);
  3576.       Result := Result + ', ' + str;
  3577.     end;
  3578.     if primary = LANG_KOREAN then
  3579.     begin
  3580.       if codePage = KOREAN_JOHAB_CP_C then
  3581.       begin
  3582.         str := 'Johab';
  3583.         if translate then
  3584.           str := dictionary.Translate(str);
  3585.         Result := Result + ', ' + str;
  3586.       end;
  3587.     end;
  3588.   end
  3589.   else
  3590.   begin
  3591.     Result := language;
  3592.     if translate then
  3593.       Result := dictionary.Translate(Result);
  3594.   end;
  3595.  
  3596.   parser.Free;
  3597. end;
  3598.  
  3599. class function TIvDictionary.ComposeCountryName(
  3600.   country: String;
  3601.   primary, sub: Integer;
  3602.   translate: Boolean;
  3603.   dictionary: TIvDictionary): String;
  3604. begin
  3605.   if translate and (dictionary = nil) then
  3606.     dictionary := GetDefaultDictionary;
  3607.  
  3608.   Result := country;
  3609.   if primary = LANG_NORWEGIAN then
  3610.   begin
  3611.     if sub = SUBLANG_NORWEGIAN_BOKMAL then
  3612.       Result := 'Bokmal'
  3613.     else if sub = SUBLANG_NORWEGIAN_NYNORSK then
  3614.       Result := 'Nynorsk';
  3615.   end
  3616.   else if primary = LANG_KOREAN then
  3617.   begin
  3618.     if sub = SUBLANG_KOREAN_JOHAB then
  3619.       Result := 'Johab';
  3620.   end;
  3621.  
  3622.   if translate then
  3623.     Result := dictionary.Translate(Result);
  3624. end;
  3625.  
  3626. class function TIvDictionary.ComposeLocaleName(
  3627.   language, country: String;
  3628.   primary, sub, codePage: Integer;
  3629.   translate: Boolean;
  3630.   dictionary: TIvDictionary): String;
  3631. var
  3632.   str: String;
  3633.   parser: TIvStringParser;
  3634. begin
  3635.   if translate and (dictionary = nil) then
  3636.     dictionary := GetDefaultDictionary;
  3637.  
  3638.   parser := TIvStringParser.CreateValue(language, ' ');
  3639.   if primary = LANG_NORWEGIAN then
  3640.   begin
  3641.     parser.Separator := ' ';
  3642.     Result := parser.GetString;
  3643.     if sub = SUBLANG_NORWEGIAN_BOKMAL then
  3644.       country := 'Bokmal'
  3645.     else if sub = SUBLANG_NORWEGIAN_NYNORSK then
  3646.       country := 'Nynorsk';
  3647.  
  3648.     if translate then
  3649.       Result := dictionary.Translate(Result);
  3650.   end
  3651.   else if primary = LANG_SPANISH then
  3652.   begin
  3653.     parser.Separator := ' ';
  3654.     Result := parser.GetString;
  3655.  
  3656.     if translate then
  3657.       Result := dictionary.Translate(Result);
  3658.   end
  3659.   else if primary = LANG_SERBIAN then
  3660.   begin
  3661.     parser.Separator := ' ';
  3662.     Result := parser.GetString;
  3663.     if sub = SUBLANG_DEFAULT then
  3664.       Result := 'Croatian'
  3665.     else if sub = SUBLANG_SERBIAN_LATIN then
  3666.       Result := 'Serbian-Latin'
  3667.     else if sub = SUBLANG_SERBIAN_CYRILLIC then
  3668.       Result := 'Serbian';
  3669.  
  3670.     if translate then
  3671.       Result := dictionary.Translate(Result);
  3672.   end
  3673.   else if primary = LANG_CHINESE then
  3674.   begin
  3675.     parser.Separator := '(';
  3676.     Result := parser.GetString;
  3677.     if translate then
  3678.       Result := dictionary.Translate(Result);
  3679.  
  3680.     if codePage <> 0 then
  3681.     begin
  3682.       if codePage = TRADITIONAL_CHINESE_CP_C then
  3683.         str := 'Traditional'
  3684.       else
  3685.         str := 'Simplified';
  3686.     end;
  3687.  
  3688.     if translate then
  3689.       str := dictionary.Translate(str);
  3690.     Result := Result + ', ' + str;
  3691.   end
  3692.   else if primary = LANG_KOREAN then
  3693.   begin
  3694.     parser.Separator := '(';
  3695.     Result := parser.GetString;
  3696.     if translate then
  3697.       Result := dictionary.Translate(Result);
  3698.  
  3699.     if codePage <> 0 then
  3700.     begin
  3701.       if codePage = KOREAN_JOHAB_CP_C then
  3702.       begin
  3703.         str := 'Johab';
  3704.         if translate then
  3705.           str := dictionary.Translate(str);
  3706.         Result := Result + ', ' + str;
  3707.       end;
  3708.     end;
  3709.  
  3710.     if sub = SUBLANG_KOREAN_JOHAB then
  3711.       country := 'Johab';
  3712.   end
  3713.   else
  3714.   begin
  3715.     Result := language;
  3716.     if translate then
  3717.       Result := dictionary.Translate(Result);
  3718.   end;
  3719.  
  3720.   if sub <> SUBLANG_NEUTRAL then
  3721.   begin
  3722.     if translate then
  3723.       country := dictionary.Translate(country);
  3724.     Result := Result + ' (' +  country + ')';
  3725.   end;
  3726.  
  3727.   parser.Free;
  3728. end;
  3729.  
  3730. procedure TIvDictionary.GetLanguageDatas(list: TList);
  3731. var
  3732.   i, count: Integer;
  3733.   language: TIvLanguage;
  3734. begin
  3735.   count := GetLanguageCount;
  3736.   for i := 0 to count - 1 do
  3737.   begin
  3738.     language := TIvLanguage.Create;
  3739.     GetLanguageData(i, language);
  3740.     list.Add(language);
  3741.   end;
  3742. end;
  3743.  
  3744. procedure TIvDictionary.GetLocaleDatas(list: TList);
  3745. var
  3746.   i, count: Integer;
  3747.   locale: TIvLocale;
  3748. begin
  3749.   count := GetLocaleCount;
  3750.   for i := 0 to count - 1 do
  3751.   begin
  3752.     locale := TIvLocale.Create;
  3753.     GetLocaleData(i, locale);
  3754.     list.Add(locale);
  3755.   end;
  3756. end;
  3757.  
  3758. {$IFDEF WIN32}
  3759. class function TIvDictionary.GetSystemLocaleData(id: Integer; locale: TIvLocale): Boolean;
  3760. const
  3761.   TAG_C = '@*';
  3762. var
  3763.   i: Integer;
  3764. begin
  3765.   Result := False;
  3766.   if GetLocaleStr(id, LOCALE_SENGLANGUAGE, TAG_C) = TAG_C then
  3767.     Exit;
  3768.  
  3769.   { Finds from the NLS database }
  3770.  
  3771.   locale.Primary := IvGetPrimaryFromLocale(id);
  3772.   locale.Sub := IvGetSubFromLocale(id);
  3773.   locale.CodePage := StrToInt(GetLocaleStr(id, LOCALE_IDEFAULTANSICODEPAGE, '1252'));
  3774. {$IFDEF WIN32}
  3775.   locale.Charset := IvCodePageToCharset(locale.CodePage);
  3776. {$ENDIF}
  3777.   locale.IsCustom := False;
  3778.  
  3779.   locale.EnglishLanguageName := GetLocaleStr(id, LOCALE_SENGLANGUAGE, '');
  3780.   locale.EnglishCountryName := GetLocaleStr(id, LOCALE_SENGCOUNTRY, '');
  3781.   locale.NativeLanguageName := GetLocaleStr(id, LOCALE_SNATIVELANGNAME, '');
  3782.   locale.NativeCountryName := GetLocaleStr(id, LOCALE_SNATIVECTRYNAME, '');
  3783.   locale.Win16LanguageName := GetLocaleStr(id, LOCALE_SABBREVLANGNAME, '');
  3784.   locale.Win16CountryName := GetLocaleStr(id, LOCALE_SCOUNTRY, '');
  3785.  
  3786.   locale.MeasurementSystem := TIvMeasurementSystem(StrToInt(GetLocaleStr(id, LOCALE_IMEASURE, '0')));
  3787.   locale.CurrencyString := GetLocaleStr(id, LOCALE_SCURRENCY, '');
  3788.   locale.CurrencyFormat := TIvCurrencyFormat(StrToInt(GetLocaleStr(id, LOCALE_ICURRENCY, '0')));
  3789.   locale.NegCurrFormat := TIvNegativeCurrencyFormat(StrToInt(GetLocaleStr(id, LOCALE_INEGCURR, '0')));
  3790.   locale.CurrencyDecimals := StrToInt(GetLocaleStr(id, LOCALE_ICURRDIGITS, '0'));
  3791.   locale.ThousandSeparator := GetLocaleStr(id, LOCALE_STHOUSAND, ' ')[1];
  3792.   locale.DecimalSeparator := GetLocaleStr(id, LOCALE_SDECIMAL, ' ')[1];
  3793.  
  3794.   locale.DateSeparator := GetLocaleStr(id, LOCALE_SDATE, ' ')[1];
  3795.   locale.ShortDateFormat := GetLocaleStr(id, LOCALE_SSHORTDATE, '');
  3796.   locale.LongDateFormat := GetLocaleStr(id, LOCALE_SLONGDATE, '');
  3797.  
  3798.   locale.TimeSeparator := GetLocaleStr(id, LOCALE_STIME, ' ')[1];
  3799.   locale.TimeAMString := GetLocaleStr(id, LOCALE_S1159, '');
  3800.   locale.TimePMString := GetLocaleStr(id, LOCALE_S2359, '');
  3801.   locale.TimeLeadingZeros := GetLocaleStr(id, LOCALE_ITLZERO, '0') <> '0';
  3802.   locale.TimeFormat := TIvTimeFormat(StrToInt(GetLocaleStr(id, LOCALE_ITIME, '0')));
  3803.   locale.TimeMarkPosition := TIvTimeMarkPosition(StrToInt(GetLocaleStr(id, LOCALE_ITIMEMARKPOSN, '0')));
  3804.  
  3805.   locale.CalendarType := TIvCalendarType(StrToInt(GetLocaleStr(id, LOCALE_ICALENDARTYPE, '0')));
  3806.   locale.OptionalCalendarType := TIvCalendarType(StrToInt(GetLocaleStr(id, LOCALE_IOPTIONALCALENDAR, '0')));
  3807.   locale.FirstDayOfWeek := TIvDayOfWeek(StrToInt(GetLocaleStr(id, LOCALE_IFIRSTDAYOFWEEK, '0')));
  3808.   locale.FirstWeekOfYear := TIvFirstWeekOfYear(StrToInt(GetLocaleStr(id, LOCALE_IFIRSTWEEKOFYEAR, '0')));
  3809.  
  3810.   for i := 1 to 7 do
  3811.   begin
  3812.     locale.ShortDayNames[i] := GetLocaleStr(id, LOCALE_SABBREVDAYNAME1 + i - 1, '');
  3813.     locale.LongDayNames[i] := GetLocaleStr(id, LOCALE_SDAYNAME1 + i - 1, '');
  3814.   end;
  3815.  
  3816.   for i := 1 to 12 do
  3817.   begin
  3818.     locale.ShortMonthNames[i] := GetLocaleStr(id, LOCALE_SABBREVMONTHNAME1 + i - 1, '');
  3819.     locale.LongMonthNames[i] := GetLocaleStr(id, LOCALE_SMONTHNAME1 + i - 1, '');
  3820.   end;
  3821.  
  3822.   locale.Init;
  3823.   
  3824.   Result := True;
  3825. end;
  3826. {$ENDIF}
  3827.  
  3828. function TIvDictionary.GetLocaleDataById(id: Integer; locale: TIvLocale): Boolean;
  3829. var
  3830.   i: Integer;
  3831.   locales: TList;
  3832. begin
  3833.   { Finds first from the locale table }
  3834.  
  3835.   locales := TList.Create;
  3836.   try
  3837.     GetLocaleDatas(locales);
  3838.     for i := 0 to locales.Count - 1 do
  3839.     begin
  3840.       if TIvLocale(locales[i]).Locale = id then
  3841.       begin
  3842.         locale.Assign(locales[i]);
  3843.         Result := True;
  3844.         Exit;
  3845.       end;
  3846.     end;
  3847.   finally
  3848.     FreeList(locales);
  3849.   end;
  3850.  
  3851.   { Not found from the dictionary. Finds from the system locale table }
  3852.  
  3853. {$IFDEF WIN32}
  3854.   Result := GetSystemLocaleData(id, locale);
  3855. {$ELSE}
  3856.   Result := False;
  3857. {$ENDIF}
  3858. end;
  3859.  
  3860. procedure TIvDictionary.GetPrimaryLanguages(primaries: TStrings; native: Boolean);
  3861. var
  3862.   found: Boolean;
  3863.   i, j: Integer;
  3864.   languages: TList;
  3865.   language: TIvLanguage;
  3866. begin
  3867.   languages := TList.Create;
  3868.   GetLanguageDatas(languages);
  3869.  
  3870.   for i := 0 to LanguageCount - 1 do
  3871.   begin
  3872.     language := TIvLanguage(languages[i]);
  3873.  
  3874.     found := False;
  3875.     for j := 0 to i - 1 do
  3876.     begin
  3877.       if language.Primary = TIvLanguage(languages[j]).Primary then
  3878.       begin
  3879.         found := True;
  3880.         Break;
  3881.       end;
  3882.     end;
  3883.  
  3884.     if not found then
  3885.     begin
  3886.       if native then
  3887.         primaries.AddObject(language.NativeName, TObject(language.Primary))
  3888.       else
  3889.         primaries.AddObject(language.EnglishName, TObject(language.Primary));
  3890.     end;
  3891.   end;
  3892.  
  3893.   FreeList(languages);
  3894. end;
  3895.  
  3896. {$IFDEF WIN32}
  3897. class procedure TIvDictionary.GetSystemLocales(locales: TList);
  3898.  
  3899.   function EnumLocales(localeStr: PChar): Integer; stdcall;
  3900.   var
  3901.     id: Integer;
  3902.     locale: TIvLocale;
  3903.   begin
  3904.     id := StrToInt('$' + localeStr);
  3905.     locale := TIvLocale.Create;
  3906.     TIvDictionary.GetSystemLocaleData(id, locale);
  3907.     enumList.Add(locale);
  3908.     Result := 1;
  3909.   end;
  3910.  
  3911. begin
  3912.   { Gets the system locales }
  3913.  
  3914.   enumList := locales;
  3915.   EnumSystemLocales(@EnumLocales, LCID_SUPPORTED);
  3916. end;
  3917.  
  3918. class procedure TIvDictionary.GetSystemLocaleIds(locales: TList);
  3919.  
  3920.   function EnumLocales(localeStr: PChar): Integer; stdcall;
  3921.   var
  3922.     id: Integer;
  3923.   begin
  3924.     id := StrToInt('$' + localeStr);
  3925.     enumList.Add(Pointer(id));
  3926.     Result := 1;
  3927.   end;
  3928.  
  3929. begin
  3930.   { Gets the system locales }
  3931.  
  3932.   enumList := locales;
  3933.   EnumSystemLocales(@EnumLocales, LCID_SUPPORTED);
  3934. end;
  3935. {$ENDIF}
  3936.  
  3937. procedure TIvDictionary.GetLocales(locales: TList);
  3938. var
  3939.   i, j: Integer;
  3940.   found: Boolean;
  3941.   locale: TIvLocale;
  3942. begin
  3943. {$IFDEF WIN32}
  3944.   GetSystemLocales(locales);
  3945. {$ENDIF}
  3946.  
  3947.   { Gets the custom locales }
  3948.  
  3949.   for i := 0 to LocaleCount - 1 do
  3950.   begin
  3951.     locale := TIvLocale.Create;
  3952.     GetLocaleData(i, locale);
  3953.  
  3954.     { Checks if the locale already exists in the list }
  3955.  
  3956.     found := False;
  3957.     for j := 0 to locales.Count - 1 do
  3958.     begin
  3959.       if TIvLocale(locales[j]).Locale = locale.Locale then
  3960.       begin
  3961.         found := True;
  3962.         TIvLocale(locales[j]).Assign(locale);
  3963.         Break;
  3964.       end;
  3965.     end;
  3966.  
  3967.     { If not found, adds the locale to the list }
  3968.  
  3969.     if found then
  3970.       locale.Free
  3971.     else
  3972.       locales.Add(locale);
  3973.   end;
  3974. end;
  3975.  
  3976. procedure TIvDictionary.GetLocaleIds(locales: TList);
  3977. var
  3978.   i, j: Integer;
  3979.   found: Boolean;
  3980.   locale: TIvLocale;
  3981. begin
  3982. {$IFDEF WIN32}
  3983.   GetSystemLocaleIds(locales);
  3984. {$ENDIF}
  3985.  
  3986.   { Gets the custom locales }
  3987.  
  3988.   for i := 0 to LocaleCount - 1 do
  3989.   begin
  3990.     locale := TIvLocale.Create;
  3991.     GetLocaleData(i, locale);
  3992.  
  3993.     { Checks if the locale already exists in the list }
  3994.  
  3995.     found := False;
  3996.     for j := 0 to locales.Count - 1 do
  3997.     begin
  3998.       if Integer(locales[j]) = locale.Locale then
  3999.       begin
  4000.         found := True;
  4001.         Break;
  4002.       end;
  4003.     end;
  4004.  
  4005.     { If not found, adds the locale to the list }
  4006.  
  4007.     if not found then
  4008.       locales.Add(Pointer(locale.Locale));
  4009.     locale.Free
  4010.   end;
  4011. end;
  4012.  
  4013. class procedure TIvDictionary.FreeList(list: TList);
  4014. var
  4015.   i: Integer;
  4016. begin
  4017.   for i := 0 to list.Count - 1 do
  4018.     TObject(list[i]).Free;
  4019.   list.Free;
  4020. end;
  4021.  
  4022.  
  4023. {$IFNDEF WIN32}
  4024. function TIvDictionary.GetSystemDefaultLCID: Integer;
  4025. begin
  4026.   Result := GetUserDefaultLCID;
  4027. end;
  4028.  
  4029. function TIvDictionary.GetUserDefaultLCID: Integer;
  4030. const
  4031.   INTL_C = 'intl';
  4032. var
  4033.   i: Integer;
  4034.   language, country: String;
  4035.   locales: TList;
  4036.   locale: TIvLocale;
  4037. begin
  4038.   { If the user's default locale has already been determined, returns it }
  4039.  
  4040.   if userDefaultLCID <> 0 then
  4041.   begin
  4042.     Result := userDefaultLCID;
  4043.     Exit;
  4044.   end;
  4045.  
  4046.   { Win16 specifies the locale using the language code and country string.
  4047.     They are stored in WIN.INI }
  4048.  
  4049.   country := GetProfileStr(INTL_C, 'sCountry', '');
  4050.   language := GetProfileStr(INTL_C, 'sLanguage', '');
  4051.  
  4052.   locales := TList.Create;
  4053.   try
  4054.     GetLocaleDatas(locales);
  4055.  
  4056.     { Scans the locales to find the matching language code. }
  4057.  
  4058.     for i := 0 to locales.Count - 1 do
  4059.     begin
  4060.       locale := TIvLocale(locales[i]);
  4061.  
  4062.       if CompareText(language, locale.Win16LanguageName) = 0 then
  4063.       begin
  4064.         userDefaultLCID := locale.Locale;
  4065.         Result := userDefaultLCID;
  4066.         Exit;
  4067.       end;
  4068.     end;
  4069.  
  4070.     { No match found. Gets the first code where the first two characters and
  4071.       country match. }
  4072.  
  4073.     language := Copy(language, 1, 2);
  4074.     for i := 0 to locales.Count - 1 do
  4075.     begin
  4076.       locale := TIvLocale(locales[i]);
  4077.  
  4078.       if (CompareText(language, Copy(locale.Win16LanguageName, 1, 2)) = 0) and
  4079.         (CompareText(country, locale.Win16CountryName) = 0) then
  4080.       begin
  4081.         userDefaultLCID := locale.Locale;
  4082.         Result := userDefaultLCID;
  4083.         Exit;
  4084.       end;
  4085.     end;
  4086.  
  4087.     { No match found. Gets the first code where the first two characters match. }
  4088.  
  4089.     language := Copy(language, 1, 2);
  4090.     for i := 0 to locales.Count - 1 do
  4091.     begin
  4092.       locale := TIvLocale(locales[i]);
  4093.  
  4094.       if CompareText(language, Copy(locale.Win16LanguageName, 1, 2)) = 0 then
  4095.       begin
  4096.         userDefaultLCID := locale.Locale;
  4097.         Result := userDefaultLCID;
  4098.         Exit;
  4099.       end;
  4100.     end;
  4101.  
  4102.     { No match found. The default language of the dictionary is used. }
  4103.  
  4104.     userDefaultLCID := IvMakeLcId(
  4105.       IvMakeLangid(Languages[DefaultLanguage].Primary, SUBLANG_DEFAULT),
  4106.       SORT_DEFAULT);
  4107.     Result := userDefaultLCID;
  4108.   finally
  4109.     FreeList(locales);
  4110.   end;
  4111. end;
  4112. {$ENDIF}
  4113.  
  4114. procedure TIvDictionary.GetSubLanguages(
  4115.   language: TIvLanguage;
  4116.   subs: TStrings;
  4117.   native: Boolean);
  4118. var
  4119.   i, j, sub: Integer;
  4120.   locales: TList;
  4121.   locale: TIvLocale;
  4122.  
  4123.   procedure Add(locale: TIvLocale);
  4124.   var
  4125.     i: Integer;
  4126.   begin
  4127.     for i := 0 to subs.Count - 1 do
  4128.     begin
  4129.       if Integer(subs.Objects[i]) = locale.Locale then
  4130.         Exit;
  4131.     end;
  4132.  
  4133.     if native then
  4134.       subs.AddObject(locale.NativeCountryName, TObject(locale.Locale))
  4135.     else
  4136.       subs.AddObject(locale.EnglishCountryName, TObject(locale.Locale));
  4137.   end;
  4138.  
  4139. begin
  4140.   locales := TList.Create;
  4141.   GetLocales(locales);
  4142.  
  4143.   if language.SubCount = 0 then
  4144.   begin
  4145.     for i := 0 to locales.Count - 1 do
  4146.     begin
  4147.       locale := TIvLocale(locales[i]);
  4148.       if language.Primary = locale.Primary then
  4149.         Add(locale);
  4150.     end;
  4151.   end
  4152.   else
  4153.   begin
  4154.     for i := 0 to language.SubCount - 1 do
  4155.     begin
  4156.       sub := language.Subs[i];
  4157.       for j := 0 to locales.Count - 1 do
  4158.       begin
  4159.         locale := TIvLocale(locales[j]);
  4160.         if (locale.Primary = language.Primary) and (locale.Sub = sub) then
  4161.           Add(locale);
  4162.       end;
  4163.     end;
  4164.   end;
  4165.  
  4166.   FreeList(locales);
  4167. end;
  4168.  
  4169. procedure TIvDictionary.TranslateWindow(wnd: THandle; str: String; resize: Boolean);
  4170. var
  4171.   dc: HDC;
  4172.   width, style: Integer;
  4173.   rect, calcRect: TRect;
  4174.   buffer: array[0..255] of Char;
  4175. begin
  4176.   { Changes the text of the window. If resizing was allowed resized the window. }
  4177.  
  4178.   if str = '' then
  4179.   begin
  4180.     GetWindowText(wnd, buffer, Sizeof(buffer));
  4181. {$IFDEF WIN32}
  4182.     str := buffer;
  4183. {$ELSE}
  4184.     str := StrPas(buffer);
  4185. {$ENDIF}
  4186.   end;
  4187.   str := Translate(str);
  4188. {$IFDEF WIN32}
  4189.   SetWindowText(wnd, PChar(str));
  4190. {$ELSE}
  4191.   SetWindowText(wnd, StrPCopy(buffer, str));
  4192. {$ENDIF}
  4193.  
  4194.   { Resized the window }
  4195.  
  4196.   if resize then
  4197.   begin
  4198.     { Calculates the width of the text. If the current width of the windows is
  4199.       less then resizez the window. }
  4200.  
  4201.     dc := GetWindowDC(wnd);
  4202. {$IFDEF WIN32}
  4203.     SelectObject(dc, GetStockObject(DEFAULT_GUI_FONT));
  4204.     width := DrawText(dc, PChar(str), -1, calcRect, DT_LEFT or DT_CALCRECT or DT_SINGLELINE);
  4205. {$ELSE}
  4206.     SelectObject(dc, GetStockObject(SYSTEM_FONT));
  4207.     width := DrawText(dc, StrPCopy(buffer, str), -1, calcRect, DT_LEFT or DT_CALCRECT or DT_SINGLELINE);
  4208. {$ENDIF}
  4209.     ReleaseDC(wnd, dc);
  4210.     if width <= 0 then
  4211.       Exit;
  4212.  
  4213.     width := calcRect.right - calcRect.left;
  4214.     GetClassName(wnd, buffer, SizeOf(buffer));
  4215.     StrLower(buffer);
  4216. {$IFDEF WIN32}
  4217.     if buffer = 'button' then
  4218. {$ELSE}
  4219.     if StrComp(buffer, 'button') = 0 then
  4220. {$ENDIF}
  4221.     begin
  4222.       { Check box and radion buttons need some space for the input area. }
  4223.  
  4224.       style := GetWindowLong(wnd, GWL_STYLE);
  4225.       if ((style and BS_CHECKBOX) <> 0) or ((style and BS_RADIOBUTTON) <> 0) then
  4226.         width := width + 20;
  4227.     end;
  4228.  
  4229.     { If the current width is less the the needed width resizes the windows }
  4230.  
  4231.     GetWindowRect(wnd, rect);
  4232.     if (rect.right - rect.left) < width then
  4233.       SetWindowPos(wnd, 0, 0, 0, width, rect.bottom - rect.top, SWP_NOMOVE or SWP_NOZORDER);
  4234.   end;
  4235. end;
  4236.  
  4237. function TIvDictionary.IsDesignTime: Boolean;
  4238. begin
  4239. {$IFDEF IVVB}
  4240.   Result := GenericIsDesignTime(Self);
  4241. {$ELSE}
  4242.   Result := csDesigning in ComponentState;
  4243. {$ENDIF}
  4244. end;
  4245.  
  4246. { TIvDictionaries }
  4247.  
  4248. constructor TIvDictionaries.Create;
  4249. begin
  4250.   inherited Create;
  4251.   FItems := TList.Create;
  4252. end;
  4253.  
  4254. destructor TIvDictionaries.Destroy;
  4255. begin
  4256.   FItems.Free;
  4257.   inherited Destroy;
  4258. end;
  4259.  
  4260. function TIvDictionaries.GetCount: Integer;
  4261. begin
  4262.   Result := FItems.Count;
  4263. end;
  4264.  
  4265. function TIvDictionaries.GetItems(index: Integer): TIvDictionary;
  4266. begin
  4267.   Result := FItems[index];
  4268. end;
  4269.  
  4270. function TIvDictionaries.FindDictionary(const name: String): TIvDictionary;
  4271. var
  4272.   i: Integer;
  4273. begin
  4274.   for i := 0 to Count - 1 do
  4275.   begin
  4276.     Result := Items[i];
  4277.  
  4278.     if Result.DictionaryName = name then
  4279.       Exit;
  4280.   end;
  4281.  
  4282.   Result := nil;
  4283. end;
  4284.  
  4285. procedure TIvDictionaries.Add(item: TIvDictionary);
  4286. var
  4287.   i: Integer;
  4288.   name: String;
  4289. begin
  4290.   if item.DictionaryName = '' then
  4291.   begin
  4292.     i := Dictionaries.Count;
  4293.     repeat
  4294.       Inc(i);
  4295.       name := 'Dictionary' + IntToStr(i);
  4296.       item.DictionaryName := name;
  4297.     until FindDictionary(name) = nil;
  4298.   end;  
  4299.  
  4300.   FItems.Add(item);
  4301. end;
  4302.  
  4303. procedure TIvDictionaries.Remove(item: TIvDictionary);
  4304. begin
  4305.   FItems.Remove(item);
  4306. end;
  4307.  
  4308.  
  4309. { TIvCustomTranslator }
  4310.  
  4311. constructor TIvCustomTranslator.Create(owner: TComponent);
  4312. begin
  4313.   inherited Create(owner);
  4314.   FState := [];
  4315.   FTranslations := TList.Create;
  4316.   if IsDesignTime and (Dictionaries.Count > 0) then
  4317.     Dictionary := Dictionaries[0];
  4318. end;
  4319.  
  4320. destructor TIvCustomTranslator.Destroy;
  4321. begin
  4322.   ClearTranslations;
  4323.   FTranslations.Free;
  4324.   inherited Destroy;
  4325. end;
  4326.  
  4327. procedure TIvCustomTranslator.ClearTranslations;
  4328. var
  4329.   i: Integer;
  4330. begin
  4331.   for i := 0 to FTranslations.Count - 1 do
  4332.     TIvTranslation(FTranslations[i]).Free;
  4333.   FTranslations.Clear;
  4334. end;
  4335.  
  4336. procedure TIvCustomTranslator.SetDictionary(value: TIvDictionary);
  4337. begin
  4338.   if value <> FDictionary then
  4339.   begin
  4340.     if not IsDesignTime and (ivtsBound in FState) then
  4341.       UnbindAndSetNative;
  4342.     FDictionary := value;
  4343.     if FDictionary <> nil then
  4344.       FDictionaryName := FDictionary.DictionaryName;
  4345.   end;
  4346.  
  4347. {$IFDEF WIN32}
  4348.   if value <> nil then
  4349.     value.FreeNotification(Self);
  4350. {$ENDIF}
  4351. end;
  4352.  
  4353. procedure TIvCustomTranslator.SetDictionaryName(const value: String);
  4354. begin
  4355.   if FDictionaryName <> value then
  4356.   begin
  4357.     Dictionary := Dictionaries.FindDictionary(value);
  4358.     FDictionaryName := value;
  4359.   end;
  4360. end;
  4361.  
  4362. procedure TIvCustomTranslator.LanguageChanged(languageChanged, localeChanged: Boolean);
  4363. begin
  4364. end;
  4365.  
  4366. {$IFDEF WIN32}
  4367. procedure TIvCustomTranslator.TranslateSystemMenu(handle: THandle; mdi: Boolean);
  4368. var
  4369.   i, j, count: Integer;
  4370.   str, current: String;
  4371.   menu: THandle;
  4372.   info: TMenuItemInfo;
  4373.   buffer: array[0..255] of Char;
  4374.  
  4375.   function Translate(const str: String): String;
  4376.   var
  4377.     l, h, i, c: Integer;
  4378.     translation: TIvTranslation;
  4379.   begin
  4380.     { Tries to first find from the translation list }
  4381.  
  4382.     l := 0;
  4383.     h := FTranslations.Count - 1;
  4384.     while l <= h do
  4385.     begin
  4386.       i := (l + h) div 2;
  4387.       translation := TIvTranslation(FTranslations[i]);
  4388.       c := TIvDictionary.IvCompareStr(translation.Key, str, Dictionary.NativeLocale, False);
  4389.       if c = 0 then
  4390.       begin
  4391.         Result := translation.Current;
  4392.         if Result = '' then
  4393.           Result := str;
  4394.         Exit;
  4395.       end
  4396.       else if c < 0 then
  4397.         l := i + 1
  4398.       else
  4399.         h := i - 1;
  4400.     end;
  4401.  
  4402.     { Not found. Gets the translation from the dictionary. }
  4403.  
  4404.     Result := FDictionary.Translate(str);
  4405.   end;
  4406.  
  4407. begin
  4408.   if (FDictionary = nil) or (handle = 0) then
  4409.     Exit;
  4410.  
  4411. {$IFDEF IVBIDI}
  4412.   info.cbSize := 44;
  4413. {$ELSE}
  4414.   info.cbSize := Sizeof(info);
  4415. {$ENDIF}
  4416.   info.fMask := MIIM_TYPE or MIIM_ID;
  4417.  
  4418.   menu := GetSystemMenu(handle, False);
  4419.   count := GetMenuItemCount(menu);
  4420.   for i := 0 to count - 1 do
  4421.   begin
  4422.     { Get the menu type }
  4423.  
  4424.     info.dwTypeData := buffer;
  4425.     info.cch := Sizeof(buffer);
  4426.     if not GetMenuItemInfo(menu, i, True, info) then
  4427.       Continue;
  4428.  
  4429.     if (info.fType and MFT_SEPARATOR) = 0 then
  4430.     begin
  4431.       case info.wID of
  4432.         SC_CLOSE: str := '&Close';
  4433.         SC_RESTORE: str := '&Restore';
  4434.         SC_MOVE: str := '&Move';
  4435.         SC_SIZE: str := '&Size';
  4436.         SC_MINIMIZE: str := 'Mi&nimize';
  4437.         SC_MAXIMIZE: str := 'Ma&ximize';
  4438.         SC_NEXTWINDOW: str := '&Next';
  4439.  
  4440.         { To do! Check the following strings }
  4441.  
  4442.         SC_PREVWINDOW: str := '&Previous';
  4443.         SC_VSCROLL: str := '&Vertical Scroll';
  4444.         SC_HSCROLL: str := '&Horizontal Scroll';
  4445.         SC_MOUSEMENU: str := '&Mouse';
  4446.         SC_KEYMENU: str := '&Key';
  4447.         SC_ARRANGE: str := '&Arrange';
  4448.         SC_TASKLIST: str := '&Task List';
  4449.         SC_SCREENSAVE: str := '&Screen Saver';
  4450.         SC_HOTKEY: str := '&Hot Key';
  4451.         SC_DEFAULT: str := '&Default';
  4452.         SC_MONITORPOWER: str := '&Monitor Power';
  4453.       end;
  4454.  
  4455.       if ivtsPreScanning in FState then
  4456.         FTranslations.Add(TIvTranslation.CreateValue(str, '', ''))
  4457.       else
  4458.       begin
  4459.         str := Translate(str);
  4460.  
  4461.         { Get the current menu text }
  4462.  
  4463.         if GetMenuString(menu, i, buffer, Sizeof(buffer), MF_BYPOSITION) <> 0 then
  4464.         begin
  4465.           current := buffer;
  4466.           j := Pos(#9, current);
  4467.           if j > 0 then
  4468.           begin
  4469.             Delete(current, 1, j);
  4470.             str := str + #9 + current;
  4471.           end;
  4472.         end;
  4473.  
  4474.         { Sets the new text value to the menu }
  4475.  
  4476.         StrPCopy(buffer, str);
  4477.         info.fType := MFT_STRING;
  4478.         info.dwTypeData := buffer;
  4479.         SetMenuItemInfo(menu, i, True, info);
  4480.       end;
  4481.     end;
  4482.   end;
  4483. end;
  4484.  
  4485. { Return Window handle to a window containing the system menu.
  4486.   By default there are no window with a system menu. However,
  4487.   TIvTranslator overrides this to return a window handle to the
  4488.   Host-component and TIvTranslatorEx to the VB-form. }
  4489.  
  4490. function TIvCustomTranslator.GetSystemMenuWinHandle: THandle;
  4491. begin
  4492.   Result := 0;
  4493. end;
  4494. {$ENDIF}
  4495.  
  4496. procedure TIvCustomTranslator.TranslateHost;
  4497. begin
  4498. end;
  4499.  
  4500. procedure TIvCustomTranslator.Translate;
  4501. begin
  4502.   FState := FState + [ivtsBound];
  4503. end;
  4504.  
  4505. procedure TIvCustomTranslator.Unbind;
  4506. begin
  4507.   if (ivtsBound in FState) and (FDictionary <> nil) then
  4508.     FDictionary.RemoveTranslator(Self);
  4509.   FDictionary := nil;
  4510.   FState := [];
  4511. end;
  4512.  
  4513. procedure TIvCustomTranslator.UnbindAndSetNative;
  4514. begin
  4515.   Unbind;
  4516. end;
  4517.  
  4518. function TIvCustomTranslator.IsDesignTime: boolean;
  4519. begin
  4520. {$IFDEF IVVB}
  4521.   Result := GenericIsDesignTime(Self);
  4522. {$ELSE}
  4523.   Result := csDesigning in ComponentState;
  4524. {$ENDIF}
  4525. end;
  4526.  
  4527. { Locale functions }
  4528.  
  4529. function IvDoesLanguageRequirePro(primary: Integer): Boolean;
  4530. begin
  4531.   case primary of
  4532.     LANG_ARABIC,
  4533.     LANG_HEBREW,
  4534.     LANG_FARSI,
  4535.  
  4536.     LANG_CHINESE,
  4537.     LANG_JAPANESE,
  4538.     LANG_KOREAN,
  4539.  
  4540.     LANG_THAI,
  4541.     LANG_VIETNAMESE:
  4542.       Result := True
  4543.   else
  4544.     Result := False;
  4545.   end;
  4546. end;
  4547.  
  4548. function IvDoesLanguageRequirePro32(primary: Integer): Boolean;
  4549. begin
  4550.   case primary of
  4551.     LANG_ARABIC,
  4552.     LANG_HEBREW,
  4553.     LANG_FARSI:
  4554.       Result := True
  4555.   else
  4556.     Result := False;
  4557.   end;
  4558. end;
  4559.  
  4560. function IvMakeLangId(primaryLanguage, subLanguage: Integer): Integer;
  4561. begin
  4562.   Result := (subLanguage shl 10) or primaryLanguage;
  4563. end;
  4564.  
  4565. function IvMakeLcId(langId, sortId: Integer): Integer;
  4566. begin
  4567.   Result := (sortId shl 16) or langId;
  4568. end;
  4569.  
  4570. function IvGetPrimaryFromLocale(locale: Integer): Integer;
  4571. begin
  4572.   Result := locale and $3FF;
  4573. end;
  4574.  
  4575. function IvGetSubFromLocale(locale: Integer): Integer;
  4576. begin
  4577.   Result := (locale shr 10) and $3F;
  4578. end;
  4579.  
  4580. function IsEMUMember(locale: Integer): Boolean;
  4581. var
  4582.   sub: Integer;
  4583. begin
  4584.   { Emu countries:
  4585.     Austria (German)
  4586.     Belgium (Dutch, French)
  4587.     Finland (Finnish, Swedish)
  4588.     France (French)
  4589.     Germany (German)
  4590.     Irland (English)
  4591.     Italy (Italian)
  4592.     Luxembourg (German, French)
  4593.     Netherlands (Dutch)
  4594.     Portugal (Portuguese)
  4595.     Spain (Spanish) }
  4596.  
  4597.   sub := IvGetSubFromLocale(locale);
  4598.   Result := False;
  4599.   case IvGetPrimaryFromLocale(locale) of
  4600.     LANG_DUTCH:
  4601.       Result := (sub = SUBLANG_DUTCH) or (sub = SUBLANG_DUTCH_BELGIAN);
  4602.  
  4603.     LANG_ENGLISH:
  4604.       Result := sub = SUBLANG_ENGLISH_EIRE;
  4605.  
  4606.     LANG_FINNISH:
  4607.       Result := sub = SUBLANG_DEFAULT;
  4608.  
  4609.     LANG_FRENCH:
  4610.       Result := (sub = SUBLANG_FRENCH) or (sub = SUBLANG_FRENCH_BELGIAN) or (sub = SUBLANG_FRENCH_LUXEMBOURG);
  4611.  
  4612.     LANG_GERMAN:
  4613.       Result := (sub = SUBLANG_GERMAN) or (sub = SUBLANG_GERMAN_AUSTRIAN) or (sub = SUBLANG_GERMAN_LUXEMBOURG);
  4614.  
  4615.     LANG_ITALIAN:
  4616.       Result := sub = SUBLANG_ITALIAN;
  4617.  
  4618.     LANG_PORTUGUESE:
  4619.       Result := sub = SUBLANG_PORTUGUESE;
  4620.  
  4621.     LANG_SWEDISH:
  4622.       Result := sub = SUBLANG_SWEDISH_FINLAND;
  4623.  
  4624.     LANG_SPANISH:
  4625.       Result := sub = SUBLANG_SPANISH;
  4626.   end;
  4627. end;
  4628.  
  4629. function GetEMUPhase: TIvEMU;
  4630. var
  4631.   d: TDateTime;
  4632. begin
  4633.   { Before January 1 1999 only the local currency is used
  4634.     From January 1 1999 to January 1 2002 Euro is also used as a account currency
  4635.     From January 1 2002 to July 1 2002 both Euro and locale currencies are used
  4636.     From July 1 2002 only Euro is used
  4637.  
  4638.     Note! July 1 might be moved to an earlied date. }
  4639.  
  4640.   d := Date;
  4641.   if d < EncodeDate(1999, 1, 1) then
  4642.     Result := iveLocal
  4643.   else if d < EncodeDate(2002, 1, 1) then
  4644.     Result := iveLocalAndEuro
  4645.   else if d < EncodeDate(2002, 7, 1) then
  4646.     Result := iveEuroAndLocal
  4647.   else
  4648.     Result := iveEuro;
  4649. end;
  4650.  
  4651. {$IFDEF WIN32}
  4652. function IvGetCharSetInfo(langId: Integer): TIvCharsetInfo;
  4653. var
  4654.   i: Integer;
  4655.   flag: DWORD;
  4656.   lfs: TLocaleFontSignature;
  4657. begin
  4658.   if GetLocaleInfo(IvMakeLcId(langId, 0), LOCALE_FONTSIGNATURE, PChar(@lfs), Sizeof(lfs)) <> 0 then
  4659.   begin
  4660.     flag := 1;
  4661.     for i := 0 to CHARSET_COUNT_C - 1 do
  4662.     begin
  4663.       if (flag and lfs.fsCsbDefault[0]) <> 0 then
  4664.       begin
  4665.         Result := CHARSETSET_TO_ID_C[i];
  4666.         Exit;
  4667.       end;
  4668.       flag := flag shl 1;
  4669.     end;
  4670.   end;
  4671.   Result := CHARSETSET_TO_ID_C[0];
  4672. end;
  4673.  
  4674. function IvLangIdToCharSet(langId: Integer): TFontCharset;
  4675. begin
  4676.   Result := IvGetCharSetInfo(langId).charSet;
  4677. end;
  4678.  
  4679. function IvCodePageToCharSet(codePage: Integer): TFontCharset;
  4680. var
  4681.   i: Integer;
  4682. begin
  4683.   Result := DEFAULT_CHARSET;
  4684.   for i := 0 to CHARSET_COUNT_C - 1 do
  4685.   begin
  4686.     if CHARSETSET_TO_ID_C[i].codePage = codePage then
  4687.     begin
  4688.       Result := CHARSETSET_TO_ID_C[i].charSet;
  4689.       Exit;
  4690.     end;
  4691.   end;
  4692. end;
  4693.  
  4694.  
  4695. const
  4696.   CHARSET_CODES_C: array[TIvFontCharset] of TFontCharset =
  4697.   (
  4698.     DEFAULT_CHARSET,
  4699.     OEM_CHARSET,
  4700.     SYMBOL_CHARSET,
  4701.     MAC_CHARSET,
  4702.     ANSI_CHARSET,
  4703.     EASTEUROPE_CHARSET,
  4704.     BALTIC_CHARSET,
  4705.     RUSSIAN_CHARSET,
  4706.     GREEK_CHARSET,
  4707.     TURKISH_CHARSET,
  4708.     ARABIC_CHARSET,
  4709.     HEBREW_CHARSET,
  4710.     SHIFTJIS_CHARSET,
  4711.     HANGEUL_CHARSET,
  4712.     JOHAB_CHARSET,
  4713.     CHINESEBIG5_CHARSET,
  4714.     GB2312_CHARSET,
  4715.     THAI_CHARSET,
  4716.     VIETNAMESE_CHARSET
  4717.   );
  4718.  
  4719. function IvCharsetToCode(value: TIvFontCharset): Byte;
  4720. begin
  4721.   Result := CHARSET_CODES_C[value];
  4722. end;
  4723.  
  4724. function IvCodeToCharset(value: Byte): TIvFontCharset;
  4725. begin
  4726.   for Result := Low(TIvFontCharSet) to High(TIvFontCharSet) do
  4727.     if CHARSET_CODES_C[Result] = value then
  4728.       Exit;
  4729.   raise Exception.Create('Invalid charset code');
  4730. end;
  4731.  
  4732. procedure InitLogFont(var logFont: TLogFont; const name: String; cs: TFontCharset);
  4733. begin
  4734.   StrPCopy(logFont.lfFaceName, name);
  4735.   logFont.lfCharSet := cs;
  4736.   case logFont.lfCharSet of
  4737.     HEBREW_CHARSET, ARABIC_CHARSET: logFont.lfPitchAndFamily := 0;
  4738.   else
  4739.     logFont.lfPitchAndFamily := MONO_FONT;
  4740.   end;
  4741. end;
  4742.  
  4743. function IvGetSupportedCharsets: TIvFontCharsets;
  4744. var
  4745.   cs: TIvFontCharSet;
  4746.   supported: Boolean;
  4747.   logFont: TLogFont;
  4748.   dc: HDC;
  4749.  
  4750.   function EnumFontFamilies(
  4751.     logFont: PEnumLogFontEx;
  4752.     textMetrics: PNewTextMetricEx;
  4753.     fontType: Integer;
  4754.     var supported: Boolean): Integer; stdcall;
  4755.   begin
  4756.     supported := True;
  4757.     Result := 0;
  4758.   end;
  4759.  
  4760. begin
  4761.   dc := GetDC(0);
  4762.   Result := [];
  4763.   for cs := Low(TIvFontCharSet) to High(TIvFontCharSet) do
  4764.   begin
  4765.     InitLogFont(logFont, '', IvCharsetToCode(cs));
  4766.     supported := False;
  4767.     EnumFontFamiliesEx(dc, logFont, @EnumFontFamilies, Integer(@supported), 0);
  4768.     if supported then
  4769.       Result := Result + [cs];
  4770.   end;
  4771.   ReleaseDC(0, dc);
  4772. end;
  4773.  
  4774. function EnumFontNames(
  4775.   logFont: PEnumLogFontEx;
  4776.   textMetrics: PNewTextMetricEx;
  4777.   fontType: Integer;
  4778.   names: TStrings): Integer; stdcall;
  4779. var
  4780.   count: Integer;
  4781.   name: String;
  4782. begin
  4783.   Result := 1;
  4784.   count := names.Count;
  4785.   name := logFont.elfLogFont.lfFaceName;
  4786.   if (count = 0) or (names[count - 1] <> name) and (name[1] <> '@') then
  4787.     names.Add(name);
  4788. end;
  4789.  
  4790. procedure IvGetFontNames(charsets: TIvFontCharsets; names: TStrings);
  4791. var
  4792.   i, j: Integer;
  4793.   cs: TIvFontCharSet;
  4794.   logFont: TLogFont;
  4795.   newNames, tempNames: TStringList;
  4796.   dc: HDC;
  4797. begin
  4798.   dc := GetDC(0);
  4799.  
  4800.   { Gets all the font names }
  4801.  
  4802.   InitLogFont(logFont, '', DEFAULT_CHARSET);
  4803.   names.Clear;
  4804.   EnumFontFamiliesEx(dc, logFont, @EnumFontNames, Integer(names), 0);
  4805.  
  4806.   for cs := Low(TIvFontCharSet) to High(TIvFontCharSet) do
  4807.   begin
  4808.     if not (cs in charsets) then
  4809.       Continue;
  4810.  
  4811.     { Gets support for each charsets }
  4812.  
  4813.     tempNames := TStringList.Create;
  4814.     InitLogFont(logFont, '', IvCharsetToCode(cs));
  4815.     EnumFontFamiliesEx(dc, logFont, @EnumFontNames, Integer(tempNames), 0);
  4816.  
  4817.     { Names and logical AND of names and tempNames }
  4818.  
  4819.     newNames := TStringList.Create;
  4820.     for i := 0 to names.Count - 1 do
  4821.     begin
  4822.       for j := 0 to tempNames.Count - 1 do
  4823.       begin
  4824.         if names[i] = tempNames[j] then
  4825.         begin
  4826.           newNames.Add(names[i]);
  4827.           Break;
  4828.         end;
  4829.       end;
  4830.     end;
  4831.     tempNames.Free;
  4832.  
  4833.     { Updates the font name list }
  4834.  
  4835.     names.Assign(newNames);
  4836.     newNames.Free;
  4837.   end;
  4838.   ReleaseDC(0, dc);
  4839. end;
  4840.  
  4841. procedure IvGetFontNamesOfCharset(charset: Integer; names: TStrings);
  4842. var
  4843.   dc: HDC;
  4844.   logFont: TLogFont;
  4845. begin
  4846.   dc := GetDC(0);
  4847.   try
  4848.     InitLogFont(logFont, '', charset);
  4849.     EnumFontFamiliesEx(dc, logFont, @EnumFontNames, Integer(names), 0);
  4850.   finally
  4851.     ReleaseDC(0, dc);
  4852.   end;
  4853. end;
  4854. {$ENDIF}
  4855.  
  4856. function IvGetCharacterSetType(locale: Integer): TIvCharacterSetType;
  4857. begin
  4858.   case IvGetPrimaryFromLocale(locale) of
  4859.     LANG_CHINESE, LANG_JAPANESE, LANG_KOREAN: Result := ivcsMultiByte;
  4860.     LANG_ARABIC, LANG_HEBREW, LANG_FARSI: Result := ivcsBiDirectional;
  4861.   else
  4862.     Result := ivcsSingleByte;
  4863.   end;
  4864. end;
  4865.  
  4866. function IvIsLocaleSingleByte(locale: Integer): Boolean;
  4867. begin
  4868.   Result := IvGetCharacterSetType(locale) = ivcsSingleByte;
  4869. end;
  4870.  
  4871. function IvIsLocaleMultiByte(locale: Integer): Boolean;
  4872. begin
  4873.   Result := IvGetCharacterSetType(locale) = ivcsMultiByte;
  4874. end;
  4875.  
  4876. function IvIsLocaleBidirectional(locale: Integer): Boolean;
  4877. begin
  4878.   Result := IvGetCharacterSetType(locale) = ivcsBiDirectional;
  4879. end;
  4880.  
  4881. {$IFDEF WIN32}
  4882. function IvWStrToStr(const source: TIvWideString; codePage: Integer): String;
  4883. var
  4884.   len: Integer;
  4885. begin
  4886.   // Calculates the size of the ansi string, sets the string length and
  4887.   // converts the string
  4888.  
  4889. {$IFDEF IVWIDE}
  4890.   if source = '' then
  4891. {$ELSE}
  4892.   if source^ = Chr(0) then
  4893. {$ENDIF}
  4894.     Result := ''
  4895.   else
  4896.   begin
  4897.     len := WideCharToMultiByte(codePage, 0, PWideChar(source), -1, nil, 0, nil, nil);
  4898.     SetLength(Result, len - 1);
  4899.     WideCharToMultiByte(codePage, 0, PWideChar(source), -1, PChar(Result), len, nil, nil);
  4900.   end;
  4901. end;
  4902.  
  4903. function IvStrToWStr(const source: String; codePage: Integer): TIvWideString;
  4904. var
  4905.   len: Integer;
  4906. begin
  4907.   if source = '' then
  4908.     Result := ''
  4909.   else
  4910.   begin
  4911.     // Calculates the size of the string
  4912.  
  4913.     len := MultiByteToWideChar(codePage, 0, PChar(source), -1, nil, 0);
  4914.  
  4915. {$IFDEF IVWIDE}
  4916.     // Sets the string length and converts the string
  4917.  
  4918.     SetLength(Result, len - 1);
  4919.     MultiByteToWideChar(codePage, 0, PChar(source), -1, PWideChar(Result), len);
  4920. {$ELSE}
  4921.     // Frees the current commaon string, allocates the new one and
  4922.     // converts the string
  4923.  
  4924.     SysFreeString(commonWideString);
  4925.     commonWideString := SysAllocStringLen(nil, len);
  4926.     commonWideString[MultiByteToWideChar(codePage, 0, PChar(source), -1, commonWideString, len)] := #0;
  4927.     Result := commonWideString;
  4928. {$ENDIF}
  4929.   end;
  4930. end;
  4931.  
  4932. function IvStrLen(const str: String; codePage: Integer): Integer;
  4933. begin
  4934.   Result := MultiByteToWideChar(codePage, 0, PChar(str), -1, nil, 0) - 1;
  4935. end;
  4936.  
  4937. function IvWStrPCopy(dest: PWideChar; const source: TIvWideString): PWideChar;
  4938. var
  4939.   i, len: Integer;
  4940. begin
  4941.   Result := dest;
  4942. {$IFDEF IVWIDE}
  4943.   len := Length(source);
  4944.   for i := 1 to len do
  4945. {$ELSE}
  4946.   len := SysStringLen(source);
  4947.   for i := 0 to len - 1 do
  4948. {$ENDIF}
  4949.   begin
  4950.     dest^ := source[i];
  4951.     Inc(dest);
  4952.   end;
  4953.   dest^ := Chr(0);
  4954. end;
  4955.  
  4956. function IvSetKeyboardLayout(langId: Integer): HKL;
  4957. var
  4958.   i, count, tempLangId: Integer;
  4959.   kls: PHLK;
  4960.   kl: HKL;
  4961. begin
  4962.   kls := nil;
  4963.   count := GetKeyboardLayoutList(0, kls^);
  4964.   kls := AllocMem(count*Sizeof(HKL));
  4965.   count := GetKeyboardLayoutList(count, kls^);
  4966.  
  4967.   { Tries exact match }
  4968.  
  4969.   for i := 0 to count - 1 do
  4970.   begin
  4971.     kl := PHLK(PChar(kls) + i*Sizeof(HKL))^;
  4972.     tempLangId := kl and $FF;
  4973.     if tempLangId = langId then
  4974.     begin
  4975.       Result := ActivateKeyboardLayout(kl, 0);
  4976.       Exit;
  4977.     end;
  4978.   end;
  4979.  
  4980.   { Tries neutral match }
  4981.  
  4982.   langId := IvMakeLangId(IvGetPrimaryFromLocale(langId), SUBLANG_NEUTRAL);
  4983.   for i := 0 to count - 1 do
  4984.   begin
  4985.     kl := PHLK(PChar(kls) + i*Sizeof(HKL))^;
  4986.     tempLangId := kl and $FF;
  4987.     if tempLangId = langId then
  4988.     begin
  4989.       Result := ActivateKeyboardLayout(kl, 0);
  4990.       Exit;
  4991.     end;
  4992.   end;
  4993.  
  4994.   Result := IvResetKeyboardLayout;
  4995. end;
  4996.  
  4997. function IvResetKeyboardLayout: HKL;
  4998. begin
  4999.   Result := ActivateKeyboardLayout(KeyboardLayout, 0);
  5000. end;
  5001. {$ENDIF}
  5002.  
  5003. {$IFDEF WIN32}
  5004. const
  5005.   OLEAUT = 'oleaut32.dll';
  5006.  
  5007. function SysAllocString; external OLEAUT name 'SysAllocString';
  5008. function SysAllocStringLen; external OLEAUT name 'SysAllocStringLen';
  5009. function SysReAllocStringLen; external OLEAUT name 'SysReAllocStringLen';
  5010. procedure SysFreeString; external OLEAUT name 'SysFreeString';
  5011. function SysStringLen; external OLEAUT name 'SysStringLen';
  5012. {$ENDIF}
  5013.  
  5014. function IsDefaultDictionaryOpen: Boolean;
  5015. begin
  5016.   Result := (Dictionaries.Count >= 1) and (Dictionaries[0].IsOpen);
  5017. end;
  5018.  
  5019. {$IFDEF IVWIDE}
  5020. class procedure TIvDictionary.HandleException(sender: TObject; e: Exception);
  5021. var
  5022.   msg: String;
  5023. begin
  5024.   // Translates the exception
  5025.  
  5026.   msg := e.Message;
  5027.   if IsDefaultDictionaryOpen then
  5028.     msg := GetDefaultDictionary.Translate(msg);
  5029.  
  5030.   if (msg <> '') and (AnsiLastChar(msg) > '.') then
  5031.     msg := msg + '.';
  5032.  
  5033.   // Shows it
  5034.  
  5035.   MessageDlg(msg, mtError, [mbOK], 0);
  5036. end;
  5037.  
  5038. function TranslateLoadResString(resStringRec: PResStringRec): String;
  5039. var
  5040.   buffer: array[0..1023] of Char;
  5041. begin
  5042.   // Loads the resource string
  5043.  
  5044.   if resStringRec <> nil then
  5045.   begin
  5046.   {$IFDEF IVBIDI}
  5047.     if resStringRec.Identifier < 64*1024 then
  5048.   {$ENDIF}
  5049.     begin
  5050.       SetString(
  5051.         Result,
  5052.         buffer,
  5053.         LoadString(
  5054.           FindResourceHInstance(resStringRec.Module^),
  5055.           resStringRec.Identifier,
  5056.           buffer,
  5057.           SizeOf(buffer)));
  5058.     end
  5059.   {$IFDEF IVBIDI}
  5060.     else
  5061.       Result := PChar(resStringRec.Identifier);
  5062.   {$ENDIF}
  5063.   end;
  5064.  
  5065.   // Translates the string
  5066.  
  5067.   if (Result <> '') and resStrTranslationEnabled and IsDefaultDictionaryOpen then
  5068.   begin
  5069.     resStrTranslationEnabled := False;
  5070.     Result := GetDefaultDictionary.Translate(Result);
  5071.     resStrTranslationEnabled := True;
  5072.   end;
  5073. end;
  5074.  
  5075. function IvLoadResString(resStringRec: PResStringRec): String;
  5076. asm
  5077.   PUSH  EBP
  5078.   MOV   EBP, ESP
  5079.   ADD   ESP, $-8
  5080.   MOV   [EBP-$8], EDX
  5081.   MOV   [EBP-$4], EAX
  5082.   MOV   EDX, [EBP-$8]
  5083.   MOV   EAX, [EBP-$4]
  5084.   MOV   ECX, OFFSET Addr(TranslateLoadResString)-$1
  5085.   CALL  ECX
  5086.   MOV   ESP,EBP
  5087.   POP   EBP
  5088. end;
  5089.  
  5090. type
  5091.   TMenuKeyCap = (mkcBkSp, mkcTab, mkcEsc, mkcEnter, mkcSpace, mkcPgUp,
  5092.     mkcPgDn, mkcEnd, mkcHome, mkcLeft, mkcUp, mkcRight, mkcDown, mkcIns,
  5093.     mkcDel, mkcShift, mkcCtrl, mkcAlt);
  5094.  
  5095. function GetTranslatedMenuKeyCaps(value: TMenuKeyCap): String;
  5096. begin
  5097.   case value of
  5098.     mkcBkSp: Result := SmkcBkSp;
  5099.     mkcTab: Result := SmkcTab;
  5100.     mkcEsc: Result := SmkcEsc;
  5101.     mkcEnter: Result := SmkcEnter;
  5102.     mkcSpace: Result := SmkcSpace;
  5103.     mkcPgUp: Result := SmkcPgUp;
  5104.     mkcPgDn: Result := SmkcPgDn;
  5105.     mkcEnd: Result := SmkcEnd;
  5106.     mkcHome: Result := SmkcHome;
  5107.     mkcLeft: Result := SmkcLeft;
  5108.     mkcUp: Result := SmkcUp;
  5109.     mkcRight: Result := SmkcRight;
  5110.     mkcDown: Result := SmkcDown;
  5111.     mkcIns: Result := SmkcIns;
  5112.     mkcDel: Result := SmkcDel;
  5113.     mkcShift: Result := SmkcShift;
  5114.     mkcCtrl: Result := SmkcCtrl;
  5115.     mkcAlt: Result := SmkcAlt;
  5116.   end;
  5117.  
  5118.   if IsDefaultDictionaryOpen then
  5119.     Result := GetDefaultDictionary.Translate(Result);
  5120. end;
  5121.  
  5122. function GetSpecialName(shortCut: TShortCut): String;
  5123. var
  5124.   ScanCode: Integer;
  5125.   KeyName: array[0..255] of Char;
  5126. begin
  5127.   Result := '';
  5128.   ScanCode := MapVirtualKey(WordRec(ShortCut).Lo, 0) shl 16;
  5129.   if ScanCode <> 0 then
  5130.   begin
  5131.     GetKeyNameText(ScanCode, KeyName, SizeOf(KeyName));
  5132.     if (KeyName[1] = #0) and (KeyName[0] <> #0) then
  5133.       GetSpecialName := KeyName;
  5134.   end;
  5135. end;
  5136.  
  5137. function TranslateShortCutToText(ShortCut: TShortCut): String;
  5138. var
  5139.   Name: string;
  5140. begin
  5141.   case WordRec(ShortCut).Lo of
  5142.     $08, $09:
  5143.       Name := GetTranslatedMenuKeyCaps(TMenuKeyCap(Ord(mkcBkSp) + WordRec(ShortCut).Lo - $08));
  5144.  
  5145.     $0D:
  5146.       Name := GetTranslatedMenuKeyCaps(mkcEnter);
  5147.  
  5148.     $1B:
  5149.       Name := GetTranslatedMenuKeyCaps(mkcEsc);
  5150.  
  5151.     $20..$28:
  5152.       Name := GetTranslatedMenuKeyCaps(TMenuKeyCap(Ord(mkcSpace) + WordRec(ShortCut).Lo - $20));
  5153.  
  5154.     $2D..$2E:
  5155.       Name := GetTranslatedMenuKeyCaps(TMenuKeyCap(Ord(mkcIns) + WordRec(ShortCut).Lo - $2D));
  5156.  
  5157.     $30..$39:
  5158.       Name := Chr(WordRec(ShortCut).Lo - $30 + Ord('0'));
  5159.  
  5160.     $41..$5A:
  5161.       Name := Chr(WordRec(ShortCut).Lo - $41 + Ord('A'));
  5162.  
  5163.     $60..$69:
  5164.       Name := Chr(WordRec(ShortCut).Lo - $60 + Ord('0'));
  5165.  
  5166.     $70..$87:
  5167.       Name := 'F' + IntToStr(WordRec(ShortCut).Lo - $6F);
  5168.   else
  5169.     Name := GetSpecialName(ShortCut);
  5170.   end;
  5171.  
  5172.   if Name <> '' then
  5173.   begin
  5174.     Result := '';
  5175.     if ShortCut and scShift <> 0 then
  5176.       Result := Result + GetTranslatedMenuKeyCaps(mkcShift);
  5177.  
  5178.     if ShortCut and scCtrl <> 0 then
  5179.       Result := Result + GetTranslatedMenuKeyCaps(mkcCtrl);
  5180.  
  5181.     if ShortCut and scAlt <> 0 then
  5182.       Result := Result + GetTranslatedMenuKeyCaps(mkcAlt);
  5183.  
  5184.     Result := Result + Name;
  5185.   end
  5186.   else
  5187.     Result := '';
  5188. end;
  5189.  
  5190. function IvShortCutToText(ShortCut: TShortCut): String;
  5191. asm
  5192.   PUSH  EBP
  5193.   MOV   EBP, ESP
  5194.   ADD   ESP, $-8
  5195.   MOV   [EBP-$8], EDX
  5196.   MOV   [EBP-$4], EAX
  5197.   MOV   EDX, [EBP-$8]
  5198.   MOV   EAX, [EBP-$4]
  5199.   MOV   ECX, OFFSET Addr(TranslateShortCutToText)-$1
  5200.   CALL  ECX
  5201.   MOV   ESP,EBP
  5202.   POP   EBP
  5203. end;
  5204. {$ENDIF}
  5205.  
  5206. {$IFDEF WIN32}
  5207. initialization
  5208.   euroUsage := iveNormal;
  5209.   KeyboardLayout := GetKeyboardLayout(0);
  5210.   Dictionaries := TIvDictionaries.Create;
  5211.   {$IFDEF IVWIDE}
  5212.   resStrTranslationEnabled := True;
  5213.   loadResStringChanged := False;
  5214.   {$ENDIF}
  5215. finalization
  5216.   Dictionaries.Free;
  5217.   Dictionaries := nil;
  5218. {$ELSE}
  5219. begin
  5220.   euroUsage := iveNormal;
  5221.   Dictionaries := TIvDictionaries.Create;
  5222.   userDefaultLCID := 0;
  5223. {$ENDIF}
  5224. end.
  5225.  
  5226.